diff --git a/kernel/8259A.c b/kernel/8259A.c new file mode 100644 index 0000000000000000000000000000000000000000..5697a18b7763ed594fac555d61e77cb2bbde0f47 --- /dev/null +++ b/kernel/8259A.c @@ -0,0 +1,62 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "interrupt.h" +#include "linkage.h" +#include "lib.h" +#include "printk.h" +#include "memory.h" +#include "gate.h" +#include "ptrace.h" + +void init_8259A() +{ + int i; + for(i = 32;i < 56;i++) + { + set_intr_gate(i , 0 , interrupt[i - 32]); + } + + color_printk(RED,BLACK,"8259A init \n"); + + //8259A-master ICW1-4 + io_out8(0x20,0x11); + io_out8(0x21,0x20); + io_out8(0x21,0x04); + io_out8(0x21,0x01); + + //8259A-slave ICW1-4 + io_out8(0xa0,0x11); + io_out8(0xa1,0x28); + io_out8(0xa1,0x02); + io_out8(0xa1,0x01); + + //8259A-M/S OCW1 + io_out8(0x21,0xfd); + io_out8(0xa1,0xff); + + sti(); +} + +/* + +*/ + +void do_IRQ(struct pt_regs * regs,unsigned long nr) //regs,nr +{ + unsigned char x; + color_printk(RED,BLACK,"do_IRQ:%#018lx\t",nr); + x = io_in8(0x60); + color_printk(RED,BLACK,"key code:%#018lx\t",x); + io_out8(0x20,0x20); + color_printk(RED,BLACK,"regs:%#018lx\t\n",regs,regs->rip,regs->rsp); +} + + + diff --git a/kernel/8259A.h b/kernel/8259A.h new file mode 100644 index 0000000000000000000000000000000000000000..fecf097cf4dbbddb51a91265ab3bab4ba1cf9ef4 --- /dev/null +++ b/kernel/8259A.h @@ -0,0 +1,29 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __8259A_H__ + +#define __8259A_H__ + +#include "ptrace.h" + + +/* + +*/ + +void init_8259A(); + +/* + +*/ + +void do_IRQ(struct pt_regs * regs,unsigned long nr); + +#endif diff --git a/kernel/APIC.c b/kernel/APIC.c new file mode 100644 index 0000000000000000000000000000000000000000..4af18f0e7f52171540b052fd059edc08e316c582 --- /dev/null +++ b/kernel/APIC.c @@ -0,0 +1,421 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "interrupt.h" +#include "linkage.h" +#include "lib.h" +#include "printk.h" +#include "memory.h" +#include "gate.h" +#include "ptrace.h" +#include "cpu.h" +#include "APIC.h" +#include "schedule.h" +#include "SMP.h" + +/* + +*/ + +void IOAPIC_enable(unsigned long irq) +{ + unsigned long value = 0; + value = ioapic_rte_read((irq - 32) * 2 + 0x10); + value = value & (~0x10000UL); + ioapic_rte_write((irq - 32) * 2 + 0x10,value); +} + +void IOAPIC_disable(unsigned long irq) +{ + unsigned long value = 0; + value = ioapic_rte_read((irq - 32) * 2 + 0x10); + value = value | 0x10000UL; + ioapic_rte_write((irq - 32) * 2 + 0x10,value); +} + +unsigned long IOAPIC_install(unsigned long irq,void * arg) +{ + struct IO_APIC_RET_entry *entry = (struct IO_APIC_RET_entry *)arg; + ioapic_rte_write((irq - 32) * 2 + 0x10,*(unsigned long *)entry); + + return 1; +} + +void IOAPIC_uninstall(unsigned long irq) +{ + ioapic_rte_write((irq - 32) * 2 + 0x10,0x10000UL); +} + +void IOAPIC_level_ack(unsigned long irq) +{ + __asm__ __volatile__( "movq $0x00, %%rdx \n\t" + "movq $0x00, %%rax \n\t" + "movq $0x80b, %%rcx \n\t" + "wrmsr \n\t" + :::"memory"); + + *ioapic_map.virtual_EOI_address = irq; +} + +void IOAPIC_edge_ack(unsigned long irq) +{ + __asm__ __volatile__( "movq $0x00, %%rdx \n\t" + "movq $0x00, %%rax \n\t" + "movq $0x80b, %%rcx \n\t" + "wrmsr \n\t" + :::"memory"); +} + +void Local_APIC_edge_level_ack(unsigned long irq) +{ + __asm__ __volatile__( "movq $0x00, %%rdx \n\t" + "movq $0x00, %%rax \n\t" + "movq $0x80b, %%rcx \n\t" + "wrmsr \n\t" + :::"memory"); +} + +/* + +*/ + +unsigned long ioapic_rte_read(unsigned char index) +{ + unsigned long ret; + + *ioapic_map.virtual_index_address = index + 1; + io_mfence(); + ret = *ioapic_map.virtual_data_address; + ret <<= 32; + io_mfence(); + + *ioapic_map.virtual_index_address = index; + io_mfence(); + ret |= *ioapic_map.virtual_data_address; + io_mfence(); + + return ret; +} + +/* + +*/ + +void ioapic_rte_write(unsigned char index,unsigned long value) +{ + *ioapic_map.virtual_index_address = index; + io_mfence(); + *ioapic_map.virtual_data_address = value & 0xffffffff; + value >>= 32; + io_mfence(); + + *ioapic_map.virtual_index_address = index + 1; + io_mfence(); + *ioapic_map.virtual_data_address = value & 0xffffffff; + io_mfence(); +} + +/* + +*/ + +void IOAPIC_pagetable_remap() +{ + unsigned long * tmp; + unsigned char * IOAPIC_addr = (unsigned char *)Phy_To_Virt(0xfec00000); + + ioapic_map.physical_address = 0xfec00000; + ioapic_map.virtual_index_address = IOAPIC_addr; + ioapic_map.virtual_data_address = (unsigned int *)(IOAPIC_addr + 0x10); + ioapic_map.virtual_EOI_address = (unsigned int *)(IOAPIC_addr + 0x40); + + tmp = Phy_To_Virt(Get_gdt() + (((unsigned long)IOAPIC_addr >> PAGE_GDT_SHIFT) & 0x1ff)); + if (*tmp == 0) + { + unsigned long * virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_mpl4t(tmp,mk_mpl4t(Virt_To_Phy(virtual),PAGE_KERNEL_GDT)); + } + + color_printk(YELLOW,BLACK,"1:%#018lx\t%#018lx\n",(unsigned long)tmp,(unsigned long)*tmp); + + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + (((unsigned long)IOAPIC_addr >> PAGE_1G_SHIFT) & 0x1ff)); + if(*tmp == 0) + { + unsigned long * virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_pdpt(tmp,mk_pdpt(Virt_To_Phy(virtual),PAGE_KERNEL_Dir)); + } + + color_printk(YELLOW,BLACK,"2:%#018lx\t%#018lx\n",(unsigned long)tmp,(unsigned long)*tmp); + + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + (((unsigned long)IOAPIC_addr >> PAGE_2M_SHIFT) & 0x1ff)); + set_pdt(tmp,mk_pdt(ioapic_map.physical_address,PAGE_KERNEL_Page | PAGE_PWT | PAGE_PCD)); + + color_printk(BLUE,BLACK,"3:%#018lx\t%#018lx\n",(unsigned long)tmp,(unsigned long)*tmp); + + color_printk(BLUE,BLACK,"ioapic_map.physical_address:%#010x\t\t\n",ioapic_map.physical_address); + color_printk(BLUE,BLACK,"ioapic_map.virtual_address:%#018lx\t\t\n",(unsigned long)ioapic_map.virtual_index_address); + + flush_tlb(); +} + +/* + +*/ + +void Local_APIC_init() +{ + unsigned int x,y; + unsigned int a,b,c,d; + + //check APIC & x2APIC support + get_cpuid(1,0,&a,&b,&c,&d); + //void get_cpuid(unsigned int Mop,unsigned int Sop,unsigned int * a,unsigned int * b,unsigned int * c,unsigned int * d) + color_printk(WHITE,BLACK,"CPUID\t01,eax:%#010x,ebx:%#010x,ecx:%#010x,edx:%#010x\n",a,b,c,d); + + if((1<<9) & d) + color_printk(WHITE,BLACK,"HW support APIC&xAPIC\t"); + else + color_printk(WHITE,BLACK,"HW NO support APIC&xAPIC\t"); + + if((1<<21) & c) + color_printk(WHITE,BLACK,"HW support x2APIC\n"); + else + color_printk(WHITE,BLACK,"HW NO support x2APIC\n"); + + //enable xAPIC & x2APIC + __asm__ __volatile__( "movq $0x1b, %%rcx \n\t" + "rdmsr \n\t" + "bts $10, %%rax \n\t" + "bts $11, %%rax \n\t" + "wrmsr \n\t" + "movq $0x1b, %%rcx \n\t" + "rdmsr \n\t" + :"=a"(x),"=d"(y) + : + :"memory"); + + color_printk(WHITE,BLACK,"eax:%#010x,edx:%#010x\t",x,y); + + if(x&0xc00) + color_printk(WHITE,BLACK,"xAPIC & x2APIC enabled\n"); + + //enable SVR[8] + __asm__ __volatile__( "movq $0x80f, %%rcx \n\t" + "rdmsr \n\t" + "bts $8, %%rax \n\t" + "bts $12, %%rax\n\t" + "wrmsr \n\t" + "movq $0x80f, %%rcx \n\t" + "rdmsr \n\t" + :"=a"(x),"=d"(y) + : + :"memory"); + + color_printk(WHITE,BLACK,"eax:%#010x,edx:%#010x\t",x,y); + + if(x&0x100) + color_printk(WHITE,BLACK,"SVR[8] enabled\n"); + if(x&0x1000) + color_printk(WHITE,BLACK,"SVR[12] enabled\n"); + + //get local APIC ID + __asm__ __volatile__( "movq $0x802, %%rcx \n\t" + "rdmsr \n\t" + :"=a"(x),"=d"(y) + : + :"memory"); + + color_printk(WHITE,BLACK,"eax:%#010x,edx:%#010x\tx2APIC ID:%#010x\n",x,y,x); + + //get local APIC version + __asm__ __volatile__( "movq $0x803, %%rcx \n\t" + "rdmsr \n\t" + :"=a"(x),"=d"(y) + : + :"memory"); + + color_printk(WHITE,BLACK,"local APIC Version:%#010x,Max LVT Entry:%#010x,SVR(Suppress EOI Broadcast):%#04x\t",x & 0xff,(x >> 16 & 0xff) + 1,x >> 24 & 0x1); + + if((x & 0xff) < 0x10) + color_printk(WHITE,BLACK,"82489DX discrete APIC\n"); + + else if( ((x & 0xff) >= 0x10) && ((x & 0xff) <= 0x15) ) + color_printk(WHITE,BLACK,"Integrated APIC\n"); + + //mask all LVT + __asm__ __volatile__( "movq $0x82f, %%rcx \n\t" //CMCI + "wrmsr \n\t" + "movq $0x832, %%rcx \n\t" //Timer + "wrmsr \n\t" + "movq $0x833, %%rcx \n\t" //Thermal Monitor + "wrmsr \n\t" + "movq $0x834, %%rcx \n\t" //Performance Counter + "wrmsr \n\t" + "movq $0x835, %%rcx \n\t" //LINT0 + "wrmsr \n\t" + "movq $0x836, %%rcx \n\t" //LINT1 + "wrmsr \n\t" + "movq $0x837, %%rcx \n\t" //Error + "wrmsr \n\t" + : + :"a"(0x10000),"d"(0x00) + :"memory"); + + color_printk(GREEN,BLACK,"Mask ALL LVT\n"); + + //TPR + __asm__ __volatile__( "movq $0x808, %%rcx \n\t" + "rdmsr \n\t" + :"=a"(x),"=d"(y) + : + :"memory"); + + color_printk(GREEN,BLACK,"Set LVT TPR:%#010x\t",x); + + //PPR + __asm__ __volatile__( "movq $0x80a, %%rcx \n\t" + "rdmsr \n\t" + :"=a"(x),"=d"(y) + : + :"memory"); + + color_printk(GREEN,BLACK,"Set LVT PPR:%#010x\n",x); +} + +/* + +*/ + +void IOAPIC_init() +{ + int i ; + // I/O APIC + // I/O APIC ID + *ioapic_map.virtual_index_address = 0x00; + io_mfence(); + *ioapic_map.virtual_data_address = 0x0f000000; + io_mfence(); + color_printk(GREEN,BLACK,"Get IOAPIC ID REG:%#010x,ID:%#010x\n",*ioapic_map.virtual_data_address, *ioapic_map.virtual_data_address >> 24 & 0xf); + io_mfence(); + + // I/O APIC Version + *ioapic_map.virtual_index_address = 0x01; + io_mfence(); + color_printk(GREEN,BLACK,"Get IOAPIC Version REG:%#010x,MAX redirection enties:%#08d\n",*ioapic_map.virtual_data_address ,((*ioapic_map.virtual_data_address >> 16) & 0xff) + 1); + + //RTE + for(i = 0x10;i < 0x40;i += 2) + ioapic_rte_write(i,0x10020 + ((i - 0x10) >> 1)); + + color_printk(GREEN,BLACK,"I/O APIC Redirection Table Entries Set Finished.\n"); +} + +/* + +*/ + +void APIC_IOAPIC_init() +{ + // init trap abort fault + int i ; + unsigned int x; + unsigned int * p = NULL; + + IOAPIC_pagetable_remap(); + + for(i = 32;i < 56;i++) + { + set_intr_gate(i , 0 , interrupt[i - 32]); + } + + //mask 8259A + color_printk(GREEN,BLACK,"MASK 8259A\n"); + io_out8(0x21,0xff); + io_out8(0xa1,0xff); + + //enable IMCR + io_out8(0x22,0x70); + io_out8(0x23,0x01); + + //init local apic + Local_APIC_init(); + + //init ioapic + IOAPIC_init(); + +/* for VMware platform, do not need to enable IOAPIC.*/ +#if 0 + //get RCBA address + io_out32(0xcf8,0x8000f8f0); + x = io_in32(0xcfc); + color_printk(RED,BLACK,"Get RCBA Address:%#010x\n",x); + x = x & 0xffffc000; + color_printk(RED,BLACK,"Get RCBA Address:%#010x\n",x); + + //get OIC address + if(x > 0xfec00000 && x < 0xfee00000) + { + p = (unsigned int *)Phy_To_Virt(x + 0x31feUL); + } + + //enable IOAPIC + x = (*p & 0xffffff00) | 0x100; + io_mfence(); + *p = x; + io_mfence(); +#endif + memset(interrupt_desc,0,sizeof(irq_desc_T)*NR_IRQS); + + //open IF eflages +// sti(); +} + +/* + +*/ + +void do_IRQ(struct pt_regs * regs,unsigned long nr) //regs:rsp,nr +{ + switch(nr & 0x80) + { + case 0x00: + + { + irq_desc_T * irq = &interrupt_desc[nr - 32]; + + if(irq->handler != NULL) + irq->handler(nr,irq->parameter,regs); + + if(irq->controller != NULL && irq->controller->ack != NULL) + irq->controller->ack(nr); + } + break; + + case 0x80: + +// color_printk(RED,BLACK,"SMP IPI:%d,CPU:%d\n",nr,SMP_cpu_id()); + Local_APIC_edge_level_ack(nr); + { + irq_desc_T * irq = &SMP_IPI_desc[nr - 200]; + + if(irq->handler != NULL) + irq->handler(nr,irq->parameter,regs); + } + + break; + + default: + + color_printk(RED,BLACK,"do_IRQ receive:%d\n",nr); + break; + } +} + diff --git a/kernel/APIC.h b/kernel/APIC.h new file mode 100644 index 0000000000000000000000000000000000000000..c664c8035d2a26e550460160d877c0fd7ae2846d --- /dev/null +++ b/kernel/APIC.h @@ -0,0 +1,275 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __APIC_H__ + +#define __APIC_H__ + +#include "ptrace.h" +#include "interrupt.h" + +/* + +0~255 IDT + +0 ~ 31 trap fault abort for system + 0 devide error + 1 debug + 2 NMI + 3 breakpoint + 4 overflow + 5 bound range + 6 undefined opcode + 7 device not available + 8 double fault + 9 coprocessor segment overrun + 10 invalid TSS + 11 segment not present + 12 stack segment fault + 13 general protection + 14 page fault + 15 + 16 x87 FPU error + 17 alignment check + 18 machine check + 19 SIMD exception + 20 virtualization exception +21 ~ 31 Do not use + +32 ~ 55 I/O APIC + 32 8259A + 33 keyboard + 34 HPET timer 0,8254 counter 0 + 35 serial port A + 36 serial port B + 37 parallel port + 38 floppy + 39 parallel port + 40 RTC,HPET timer 1 + 41 Generic + 42 Generic + 43 HPET timer 2 + 44 HPET timer 3 + 45 FERR# + 46 SATA primary + 47 SATA secondary + 48 PIRQA + 49 PIRQB + 50 PIRQC + 51 PIRQD + 52 PIRQE + 53 PIRQF + 54 PIRQG + 55 PIRQH + + +0x80 system call + +150 ~ 200 Local APIC + 150 CMCI + 151 Timer + 152 Thermal Monitor + 153 Performance Counter + 154 LINT0 + 155 LINT1 + 156 Error + +200 ~ 255 MP IPI + +*/ + +/* + +1: LVT CMCI +2: LVT Timer +3: LVT Thermal Monitor +4: LVT Performace Counter +5: LVT LINT0 +6: LVT LINT1 +7: LVT Error + +*/ + +/* + LVT +*/ + +struct APIC_LVT +{ + unsigned int vector :8, //0~7 ALL + deliver_mode :3, //8~10 CMCI LINT0 LINT1 PerformCounter ThermalSensor + res_1 :1, //11 + deliver_status :1, //12 ALL + polarity:1, //13 LINT0 LINT1 + irr :1, //14 LINT0 LINT1 + trigger :1, //15 LINT0 LINT1 + mask :1, //16 ALL + timer_mode :2, //17~18 Timer + res_2 :13; //19~31 +}__attribute__((packed)); //disable align in struct + +/* + ICR +*/ + +struct INT_CMD_REG +{ + unsigned int vector :8, //0~7 + deliver_mode :3, //8~10 + dest_mode :1, //11 + deliver_status :1, //12 + res_1 :1, //13 + level :1, //14 + trigger :1, //15 + res_2 :2, //16~17 + dest_shorthand :2, //18~19 + res_3 :12; //20~31 + + union { + struct { + unsigned int res_4 :24, //32~55 + dest_field :8; //56~63 + }apic_destination; + + unsigned int x2apic_destination; //32~63 + }destination; + +}__attribute__((packed)); + +/* + RTE +*/ + +struct IO_APIC_RET_entry +{ + unsigned int vector :8, //0~7 + deliver_mode :3, //8~10 + dest_mode :1, //11 + deliver_status :1, //12 + polarity:1, //13 + irr :1, //14 + trigger :1, //15 + mask :1, //16 + reserved:15; //17~31 + + union{ + struct { + unsigned int reserved1 :24, //32~55 + phy_dest :4, //56~59 + reserved2 :4; //60~63 + }physical; + + struct { + unsigned int reserved1 :24, //32~55 + logical_dest :8; //56~63 + }logical; + }destination; +}__attribute__((packed)); + +/* + +*/ + +//delivery mode +#define APIC_ICR_IOAPIC_Fixed 0 //LAPIC IOAPIC ICR +#define IOAPIC_ICR_Lowest_Priority 1 // IOAPIC ICR +#define APIC_ICR_IOAPIC_SMI 2 //LAPIC IOAPIC ICR + +#define APIC_ICR_IOAPIC_NMI 4 //LAPIC IOAPIC ICR +#define APIC_ICR_IOAPIC_INIT 5 //LAPIC IOAPIC ICR +#define ICR_Start_up 6 // ICR +#define IOAPIC_ExtINT 7 // IOAPIC + + +/* + +*/ +//timer mode +#define APIC_LVT_Timer_One_Shot 0 +#define APIC_LVT_Timer_Periodic 1 +#define APIC_LVT_Timer_TSC_Deadline 2 + +//mask +#define APIC_ICR_IOAPIC_Masked 1 +#define APIC_ICR_IOAPIC_UN_Masked 0 + +//trigger mode +#define APIC_ICR_IOAPIC_Edge 0 +#define APIC_ICR_IOAPIC_Level 1 + +//delivery status +#define APIC_ICR_IOAPIC_Idle 0 +#define APIC_ICR_IOAPIC_Send_Pending 1 + +//destination shorthand +#define ICR_No_Shorthand 0 +#define ICR_Self 1 +#define ICR_ALL_INCLUDE_Self 2 +#define ICR_ALL_EXCLUDE_Self 3 + +//destination mode +#define ICR_IOAPIC_DELV_PHYSICAL 0 +#define ICR_IOAPIC_DELV_LOGIC 1 + +//level +#define ICR_LEVEL_DE_ASSERT 0 +#define ICR_LEVLE_ASSERT 1 + +//remote irr +#define APIC_IOAPIC_IRR_RESET 0 +#define APIC_IOAPIC_IRR_ACCEPT 1 + +//pin polarity +#define APIC_IOAPIC_POLARITY_HIGH 0 +#define APIC_IOAPIC_POLARITY_LOW 1 + +/* + +*/ + +struct IOAPIC_map +{ + unsigned int physical_address; + unsigned char * virtual_index_address; + unsigned int * virtual_data_address; + unsigned int * virtual_EOI_address; +}ioapic_map; + +unsigned long ioapic_rte_read(unsigned char index); +void ioapic_rte_write(unsigned char index,unsigned long value); + +/* + +*/ + +void IOAPIC_pagetable_remap(); + +/* + +*/ + +void do_IRQ(struct pt_regs * regs,unsigned long nr); + +/* + +*/ + +void APIC_IOAPIC_init(); +void Local_APIC_init(); +void IOAPIC_init(); + +void IOAPIC_enable(unsigned long irq); +void IOAPIC_disable(unsigned long irq); +unsigned long IOAPIC_install(unsigned long irq,void * arg); +void IOAPIC_uninstall(unsigned long irq); +void IOAPIC_level_ack(unsigned long irq); +void IOAPIC_edge_ack(unsigned long irq); +void Local_APIC_edge_level_ack(unsigned long irq); + +#endif diff --git a/kernel/APU_boot.S b/kernel/APU_boot.S new file mode 100644 index 0000000000000000000000000000000000000000..39785318e4c01f0e0450bbc0af4c0070bd270df6 --- /dev/null +++ b/kernel/APU_boot.S @@ -0,0 +1,161 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "linkage.h" + +.balign 0x1000 + +.text +.code16 + +ENTRY(_APU_boot_start) + +_APU_boot_base = . + + cli + wbinvd + + mov %cs, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %ss + mov %ax, %fs + mov %ax, %gs + +# set sp + + movl $(_APU_boot_tmp_Stack_end - _APU_boot_base), %esp + +# get base address + + mov %cs, %ax + movzx %ax, %esi + shll $4, %esi + +# set gdt and 32&64 code address + + leal (_APU_Code32 - _APU_boot_base)(%esi), %eax + movl %eax, _APU_Code32_vector - _APU_boot_base + + leal (_APU_Code64 - _APU_boot_base)(%esi), %eax + movl %eax, _APU_Code64_vector - _APU_boot_base + + leal (_APU_tmp_GDT - _APU_boot_base)(%esi), %eax + movl %eax, (_APU_tmp_GDT + 2 - _APU_boot_base) + +# load idt gdt + + lidtl _APU_tmp_IDT - _APU_boot_base + lgdtl _APU_tmp_GDT - _APU_boot_base + +# enable protected mode + + smsw %ax + bts $0 ,%ax + lmsw %ax + +# go to 32 code + ljmpl *(_APU_Code32_vector - _APU_boot_base) + +.code32 +.balign 4 +_APU_Code32: +# go to 64 code + + mov $0x10, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %ss + mov %ax, %fs + mov %ax, %gs + + leal (_APU_boot_tmp_Stack_end - _APU_boot_base)(%esi), %eax + movl %eax, %esp + + +# open PAE + + movl %cr4, %eax + bts $5, %eax + movl %eax, %cr4 + +# set page table +#ifdef UEFI + movl $0x101000, %eax // UEFI bootloader, no temporary PG table +#else + movl $0x90000, %eax +#endif + movl %eax, %cr3 + +# enable long mode + + movl $0xC0000080, %ecx + rdmsr + + bts $8, %eax + wrmsr + +# enable PE & paging + + movl %cr0, %eax + bts $0, %eax + bts $31, %eax + movl %eax, %cr0 + + ljmp *(_APU_Code64_vector - _APU_boot_base)(%esi) + + +.code64 +.balign 4 +_APU_Code64: +# go to head.S + movq $0x20, %rax + movq %rax, %ds + movq %rax, %es + movq %rax, %fs + movq %rax, %gs + movq %rax, %ss + + movq $0x100000, %rax + jmpq *%rax + + hlt + +.balign 4 +_APU_tmp_IDT: + .word 0 + .word 0,0 + +.balign 4 +_APU_tmp_GDT: + .short _APU_tmp_GDT_end - _APU_tmp_GDT - 1 + .long _APU_tmp_GDT - _APU_boot_base + .short 0 + .quad 0x00cf9a000000ffff + .quad 0x00cf92000000ffff + .quad 0x0020980000000000 + .quad 0x0000920000000000 +_APU_tmp_GDT_end: + +.balign 4 +_APU_Code32_vector: + .long _APU_Code32 - _APU_boot_base + .word 0x08,0 + +.balign 4 +_APU_Code64_vector: + .long _APU_Code64 - _APU_boot_base + .word 0x18,0 + +.balign 4 +_APU_boot_tmp_Stack_start: + .org 0x400 +_APU_boot_tmp_Stack_end: + +ENTRY(_APU_boot_end) diff --git a/kernel/HPET.c b/kernel/HPET.c new file mode 100644 index 0000000000000000000000000000000000000000..3f2bdecc12c5ab5c21fd47e9b79a9a87db2bc42e --- /dev/null +++ b/kernel/HPET.c @@ -0,0 +1,114 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "HPET.h" +#include "printk.h" +#include "lib.h" +#include "APIC.h" +#include "time.h" +#include "timer.h" +#include "softirq.h" +#include "task.h" +#include "schedule.h" +#include "SMP.h" + +hw_int_controller HPET_int_controller = +{ + .enable = IOAPIC_enable, + .disable = IOAPIC_disable, + .install = IOAPIC_install, + .uninstall = IOAPIC_uninstall, + .ack = IOAPIC_edge_ack, +}; + +void HPET_handler(unsigned long nr, unsigned long parameter, struct pt_regs * regs) +{ + jiffies++; + + if((container_of(list_next(&timer_list_head.list),struct timer_list,list)->expire_jiffies <= jiffies)) + set_softirq_status(TIMER_SIRQ); + + switch(current->priority) + { + case 0: + case 1: + task_schedule[SMP_cpu_id()].CPU_exec_task_jiffies--; + current->vrun_time += 1; + break; + case 2: + default: + + task_schedule[SMP_cpu_id()].CPU_exec_task_jiffies -= 2; + current->vrun_time += 2; + break; + } + + if(task_schedule[SMP_cpu_id()].CPU_exec_task_jiffies <= 0) + current->flags |= NEED_SCHEDULE; +} + +void HPET_init() +{ + unsigned int x; + unsigned int * p = NULL; + unsigned char * HPET_addr = (unsigned char *)Phy_To_Virt(0xfed00000); + struct IO_APIC_RET_entry entry; + + //get RCBA address + io_out32(0xcf8,0x8000f8f0); + x = io_in32(0xcfc); + x = x & 0xffffc000; + + //get HPTC address + if(x > 0xfec00000 && x < 0xfee00000) + { + p = (unsigned int *)Phy_To_Virt(x + 0x3404UL); + } + + //enable HPET + *p = 0x80; + io_mfence(); + + //init I/O APIC IRQ2 => HPET Timer 0 + entry.vector = 34; + entry.deliver_mode = APIC_ICR_IOAPIC_Fixed ; + entry.dest_mode = ICR_IOAPIC_DELV_PHYSICAL; + entry.deliver_status = APIC_ICR_IOAPIC_Idle; + entry.polarity = APIC_IOAPIC_POLARITY_HIGH; + entry.irr = APIC_IOAPIC_IRR_RESET; + entry.trigger = APIC_ICR_IOAPIC_Edge; + entry.mask = APIC_ICR_IOAPIC_Masked; + entry.reserved = 0; + + entry.destination.physical.reserved1 = 0; + entry.destination.physical.phy_dest = 0; + entry.destination.physical.reserved2 = 0; + + register_irq(34, &entry , &HPET_handler, NULL, &HPET_int_controller, "HPET"); + +// color_printk(RED,BLACK,"HPET - GCAP_ID:<%#018lx>\n",*(unsigned long *)HPET_addr); + + *(unsigned long *)(HPET_addr + 0x10) = 3; + io_mfence(); + + //edge triggered & periodic + *(unsigned long *)(HPET_addr + 0x100) = 0x004c; + io_mfence(); + + //1S + *(unsigned long *)(HPET_addr + 0x108) = 14318179; + io_mfence(); + + //init MAIN_CNT & get CMOS time + get_cmos_time(&time); + *(unsigned long *)(HPET_addr + 0xf0) = 0; + io_mfence(); + +// color_printk(RED,BLACK,"year:%#010x,month:%#010x,day:%#010x,hour:%#010x,mintue:%#010x,second:%#010x\n",time.year,time.month,time.day,time.hour,time.minute,time.second); +} diff --git a/kernel/HPET.h b/kernel/HPET.h new file mode 100644 index 0000000000000000000000000000000000000000..d6e9f4c72865b7c8cfe48d0beeed3e1ea046dd8b --- /dev/null +++ b/kernel/HPET.h @@ -0,0 +1,16 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __HPET_H__ + +#define __HPET_H__ + +void HPET_init(); + +#endif diff --git a/kernel/Makefile b/kernel/Makefile index 1fcd8772abc7482f944237e6dc809f9bc900b345..f18ad8173fc39ae36122c98271c7e523d31c6f53 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -7,50 +7,119 @@ # #***************************************************/ +CFLAGS := -mcmodel=large -fno-builtin -m64 -fno-stack-protector + +ASFLAGS := --64 + +PIC := APIC + +BOOT_METHOD := UEFI + all: system_tmp kallsyms.o - ld -b elf64-x86-64 -z muldefs -o system head.o entry.o main.o printk.o trap.o memory.o interrupt.o task.o sys.o syscalls.o kallsyms.o -T Kernel.lds + ld -b elf64-x86-64 -z muldefs -o system head.o entry.o APU_boot.o main.o printk.o trap.o memory.o interrupt.o PIC.o task.o cpu.o keyboard.o mouse.o serial.o disk.o SMP.o time.o HPET.o softirq.o timer.o schedule.o fat32.o VFS.o sys.o syscalls.o semaphore.o waitqueue.o kallsyms.o -T Kernel.lds objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary system kernel.bin + sudo mount -o loop ~/Desktop/MINE_UEFI-flat.vmdk /mnt/ + sudo cp kernel.bin /mnt/ + sudo umount /mnt + sudo sync -system_tmp: head.o entry.o main.o printk.o trap.o memory.o interrupt.o task.o sys.o syscalls.o - ld -b elf64-x86-64 -z muldefs -o system_tmp head.o entry.o main.o printk.o trap.o memory.o interrupt.o task.o sys.o syscalls.o -T Kernel.lds +system_tmp: head.o entry.o APU_boot.o main.o printk.o trap.o memory.o interrupt.o PIC.o task.o cpu.o keyboard.o mouse.o serial.o disk.o SMP.o time.o HPET.o softirq.o timer.o schedule.o fat32.o VFS.o sys.o syscalls.o semaphore.o waitqueue.o + ld -b elf64-x86-64 -z muldefs -o system_tmp head.o entry.o APU_boot.o main.o printk.o trap.o memory.o interrupt.o PIC.o task.o cpu.o keyboard.o mouse.o serial.o disk.o SMP.o time.o HPET.o softirq.o timer.o schedule.o fat32.o VFS.o sys.o syscalls.o semaphore.o waitqueue.o -T Kernel.lds head.o: head.S - gcc -E head.S > head.s - as --64 -o head.o head.s + gcc -E head.S -D$(BOOT_METHOD) > head.s + as $(ASFLAGS) -o head.o head.s entry.o: entry.S - gcc -E entry.S > entry.s - as --64 -o entry.o entry.s - + gcc -E entry.S > entry.s + as $(ASFLAGS) -o entry.o entry.s + +APU_boot.o: APU_boot.S + gcc -E APU_boot.S -D$(BOOT_METHOD) > APU_boot.s + as $(ASFLAGS) -o APU_boot.o APU_boot.s + main.o: main.c - gcc -mcmodel=large -fno-builtin -m64 -c main.c - + gcc $(CFLAGS) -c main.c -D$(PIC) -D$(BOOT_METHOD) + printk.o: printk.c - gcc -mcmodel=large -fno-builtin -m64 -c printk.c + gcc $(CFLAGS) -c printk.c -D$(BOOT_METHOD) trap.o: trap.c - gcc -mcmodel=large -fno-builtin -m64 -c trap.c + gcc $(CFLAGS) -c trap.c memory.o: memory.c - gcc -mcmodel=large -fno-builtin -m64 -c memory.c + gcc $(CFLAGS) -c memory.c -D$(BOOT_METHOD) interrupt.o: interrupt.c - gcc -mcmodel=large -fno-builtin -m64 -c interrupt.c + gcc $(CFLAGS) -c interrupt.c + +ifeq ($(PIC),APIC) +PIC.o: APIC.c + gcc $(CFLAGS) -c APIC.c -o PIC.o +else +PIC.o: 8259A.c + gcc $(CFLAGS) -c 8259A.c -o PIC.o +endif task.o: task.c - gcc -mcmodel=large -fno-builtin -m64 -c task.c + gcc $(CFLAGS) -c task.c + +cpu.o: cpu.c + gcc $(CFLAGS) -c cpu.c + +keyboard.o: keyboard.c + gcc $(CFLAGS) -c keyboard.c + +mouse.o: mouse.c + gcc $(CFLAGS) -c mouse.c + +serial.o: serial.c + gcc $(CFLAGS) -c serial.c + +disk.o: disk.c + gcc $(CFLAGS) -c disk.c + +SMP.o: SMP.c + gcc $(CFLAGS) -c SMP.c + +time.o: time.c + gcc $(CFLAGS) -c time.c + +HPET.o: HPET.c + gcc $(CFLAGS) -c HPET.c + +softirq.o: softirq.c + gcc $(CFLAGS) -c softirq.c + +timer.o: timer.c + gcc $(CFLAGS) -c timer.c + +schedule.o: schedule.c + gcc $(CFLAGS) -c schedule.c + +fat32.o: fat32.c + gcc $(CFLAGS) -c fat32.c + +VFS.o: VFS.c + gcc $(CFLAGS) -c VFS.c sys.o: sys.c - gcc -mcmodel=large -fno-builtin -m64 -c sys.c + gcc $(CFLAGS) -c sys.c syscalls.o: syscalls.c - gcc -mcmodel=large -fno-builtin -m64 -c syscalls.c + gcc $(CFLAGS) -c syscalls.c + +semaphore.o: semaphore.c + gcc $(CFLAGS) -c semaphore.c +waitqueue.o: waitqueue.c + gcc $(CFLAGS) -c waitqueue.c + kallsyms.o: kallsyms.c system_tmp gcc -o kallsyms kallsyms.c nm -n system_tmp | ./kallsyms > kallsyms.S gcc -c kallsyms.S clean: - rm -rf *.o *.s~ *.s *.S~ *.c~ *.h~ system system_tmp Makefile~ Kernel.lds~ kernel.bin kallsyms kallsyms.o kallsyms.S + rm -rf *.o *.s~ *.s *.S~ *.c~ *.h~ system system_tmp Makefile~ Kernel.lds~ kernel.bin kallsyms kallsyms.o kallsyms.S diff --git a/kernel/SMP.c b/kernel/SMP.c new file mode 100644 index 0000000000000000000000000000000000000000..1f1fea483b494339532d7d84ff156fb9922b6e4e --- /dev/null +++ b/kernel/SMP.c @@ -0,0 +1,153 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "SMP.h" +#include "printk.h" +#include "lib.h" +#include "gate.h" +#include "spinlock.h" +#include "interrupt.h" +#include "task.h" +#include "schedule.h" + +spinlock_T SMP_lock; +int global_i = 0; + + +void IPI_0x200(unsigned long nr, unsigned long parameter, struct pt_regs * regs) +{ + switch(current->priority) + { + case 0: + case 1: + task_schedule[SMP_cpu_id()].CPU_exec_task_jiffies--; + current->vrun_time += 1; + break; + case 2: + default: + task_schedule[SMP_cpu_id()].CPU_exec_task_jiffies -= 2; + current->vrun_time += 2; + break; + } + if(task_schedule[SMP_cpu_id()].CPU_exec_task_jiffies <= 0) + current->flags |= NEED_SCHEDULE; +} + +void SMP_init() +{ + int i; + unsigned int a,b,c,d; + + //get local APIC ID + for(i = 0;;i++) + { + get_cpuid(0xb,i,&a,&b,&c,&d); + if((c >> 8 & 0xff) == 0) + break; + color_printk(WHITE,BLACK,"local APIC ID Package_../Core_2/SMT_1,type(%x) Width:%#010x,num of logical processor(%x)\n",c >> 8 & 0xff,a & 0x1f,b & 0xff); + } + + color_printk(WHITE,BLACK,"x2APIC ID level:%#010x\tx2APIC ID the current logical processor:%#010x\n",c & 0xff,d); + + color_printk(WHITE,BLACK,"SMP copy byte:%#010x\n",(unsigned long)&_APU_boot_end - (unsigned long)&_APU_boot_start); + memcpy(_APU_boot_start,(unsigned char *)0xffff800000020000,(unsigned long)&_APU_boot_end - (unsigned long)&_APU_boot_start); + + spin_init(&SMP_lock); + + for(i = 200;i < 210;i++) + { + set_intr_gate(i , 0 , SMP_interrupt[i - 200]); + } + memset(SMP_IPI_desc,0,sizeof(irq_desc_T) * 10); + +// register_IPI(200,NULL,&IPI_0x200,NULL,NULL,"IPI 0x200"); +} + + +void Start_SMP() +{ + unsigned int x,y; + + color_printk(RED,YELLOW,"APU starting......\n"); + + //enable xAPIC & x2APIC + __asm__ __volatile__( "movq $0x1b, %%rcx \n\t" + "rdmsr \n\t" + "bts $10, %%rax \n\t" + "bts $11, %%rax \n\t" + "wrmsr \n\t" + "movq $0x1b, %%rcx \n\t" + "rdmsr \n\t" + :"=a"(x),"=d"(y) + : + :"memory"); + + if(x&0xc00) + color_printk(RED,YELLOW,"xAPIC & x2APIC enabled\n"); + + //enable SVR[8] SVR[12] + __asm__ __volatile__( "movq $0x80f, %%rcx \n\t" + "rdmsr \n\t" + "bts $8, %%rax \n\t" + "bts $12, %%rax\n\t" + "wrmsr \n\t" + "movq $0x80f, %%rcx \n\t" + "rdmsr \n\t" + :"=a"(x),"=d"(y) + : + :"memory"); + + if(x&0x100) + color_printk(RED,YELLOW,"SVR[8] enabled\n"); + if(x&0x1000) + color_printk(RED,YELLOW,"SVR[12] enabled\n"); + + //get local APIC ID + __asm__ __volatile__( "movq $0x802, %%rcx \n\t" + "rdmsr \n\t" + :"=a"(x),"=d"(y) + : + :"memory"); + + color_printk(RED,YELLOW,"x2APIC ID:%#010x\t",x); + + current->pid = global_pid++; + current->state = TASK_RUNNING; + current->flags = PF_KTHREAD; + current->next = init_task_union.task.next; + init_task_union.task.next = current; + current->parent = &init_task_union.task; + current->mm = &init_mm; + + list_init(¤t->list); + current->addr_limit = 0xffff800000000000; + current->priority = 2; + current->vrun_time = 0; + + current->thread = (struct thread_struct *)(current + 1); + memset(current->thread,0,sizeof(struct thread_struct)); + current->thread->rsp0 = _stack_start; + current->thread->rsp = _stack_start; + current->thread->fs = KERNEL_DS; + current->thread->gs = KERNEL_DS; + init_task[SMP_cpu_id()] = current; + + load_TR(10 + (global_i -1) * 2); + + spin_unlock(&SMP_lock); + current->preempt_count = 0; + + sti(); + +// if(SMP_cpu_id() == 3) +// task_init(); + + while(1) + hlt(); +} diff --git a/kernel/SMP.h b/kernel/SMP.h new file mode 100644 index 0000000000000000000000000000000000000000..8bfe77579ca55b5cec4045680fbeaa7c5a308006 --- /dev/null +++ b/kernel/SMP.h @@ -0,0 +1,29 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __SMP_H__ + +#define __SMP_H__ + +#include "spinlock.h" + +extern unsigned char _APU_boot_start[]; +extern unsigned char _APU_boot_end[]; + +extern spinlock_T SMP_lock; + +extern int global_i; + +#define SMP_cpu_id() (current->cpu_id) + +void SMP_init(); + +void Start_SMP(); + +#endif diff --git a/kernel/VFS.c b/kernel/VFS.c new file mode 100644 index 0000000000000000000000000000000000000000..22112510a5feaf6d3af88808017779e9bb1ecf53 --- /dev/null +++ b/kernel/VFS.c @@ -0,0 +1,140 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "VFS.h" +#include "lib.h" +#include "printk.h" +#include "dirent.h" +#include "errno.h" + +struct dir_entry * path_walk(char * name,unsigned long flags) +{ + char * tmpname = NULL; + int tmpnamelen = 0; + struct dir_entry * parent = root_sb->root; + struct dir_entry * path = NULL; + + while(*name == '/') + name++; + + if(!*name) + { + return parent; + } + + for(;;) + { + tmpname = name; + while(*name && (*name != '/')) + name++; + tmpnamelen = name - tmpname; + + path = (struct dir_entry *)kmalloc(sizeof(struct dir_entry),0); + memset(path,0,sizeof(struct dir_entry)); + + path->name = kmalloc(tmpnamelen+1,0); + memset(path->name,0,tmpnamelen+1); + memcpy(tmpname,path->name,tmpnamelen); + path->name_length = tmpnamelen; + + if(parent->dir_inode->inode_ops->lookup(parent->dir_inode,path) == NULL) + { + color_printk(RED,WHITE,"can not find file or dir:%s\n",path->name); + kfree(path->name); + kfree(path); + return NULL; + } + + list_init(&path->child_node); + list_init(&path->subdirs_list); + path->parent = parent; + list_add_to_behind(&parent->subdirs_list,&path->child_node); + + if(!*name) + goto last_component; + while(*name == '/') + name++; + if(!*name) + goto last_slash; + + parent = path; + } + +last_slash: +last_component: + + if(flags & 1) + { + return parent; + } + + return path; +} + +int fill_dentry(void *buf,char *name, long namelen,long type,long offset) +{ + struct dirent* dent = (struct dirent*)buf; + + if((unsigned long)buf < TASK_SIZE && !verify_area(buf,sizeof(struct dirent) + namelen)) + return -EFAULT; + + memcpy(name,dent->d_name,namelen); + dent->d_namelen = namelen; + dent->d_type = type; + dent->d_offset = offset; + return sizeof(struct dirent) + namelen; +} + +//function mount_root +struct super_block * root_sb = NULL; +struct file_system_type filesystem = {"filesystem",0}; + +struct super_block* mount_fs(char * name,struct Disk_Partition_Table_Entry * DPTE,void * buf) +{ + struct file_system_type * p = NULL; + + for(p = &filesystem;p;p = p->next) + if(!strcmp(p->name,name)) + { + return p->read_superblock(DPTE,buf); + } + return 0; +} + +unsigned long register_filesystem(struct file_system_type * fs) +{ + struct file_system_type * p = NULL; + + for(p = &filesystem;p;p = p->next) + if(!strcmp(fs->name,p->name)) + return 0; + + fs->next = filesystem.next; + filesystem.next = fs; + + return 1; +} + +unsigned long unregister_filesystem(struct file_system_type * fs) +{ + struct file_system_type * p = &filesystem; + + while(p->next) + if(p->next == fs) + { + p->next = p->next->next; + fs->next = NULL; + return 1; + } + else + p = p->next; + return 0; +} + + diff --git a/kernel/VFS.h b/kernel/VFS.h new file mode 100644 index 0000000000000000000000000000000000000000..e7608fa44cc1d6d8818dcf1887d388471f0ea4a2 --- /dev/null +++ b/kernel/VFS.h @@ -0,0 +1,150 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __VFS_H__ + +#define __VFS_H__ +#include "lib.h" + +struct Disk_Partition_Table_Entry +{ + unsigned char flags; + unsigned char start_head; + unsigned short start_sector :6, //0~5 + start_cylinder :10; //6~15 + unsigned char type; + unsigned char end_head; + unsigned short end_sector :6, //0~5 + end_cylinder :10; //6~15 + unsigned int start_LBA; + unsigned int sectors_limit; +}__attribute__((packed)); + +struct Disk_Partition_Table +{ + unsigned char BS_Reserved[446]; + struct Disk_Partition_Table_Entry DPTE[4]; + unsigned short BS_TrailSig; +}__attribute__((packed)); + +struct file_system_type +{ + char * name; + int fs_flags; + struct super_block * (*read_superblock)(struct Disk_Partition_Table_Entry * DPTE,void * buf); + struct file_system_type * next; +}; + +struct super_block * mount_fs(char * name,struct Disk_Partition_Table_Entry * DPTE,void * buf); +unsigned long register_filesystem(struct file_system_type * fs); +unsigned long unregister_filesystem(struct file_system_type * fs); + +struct super_block_operations; +struct index_node_operations; +struct dir_entry_operations; +struct file_operations; + +struct super_block +{ + struct dir_entry * root; + + struct super_block_operations * sb_ops; + + void * private_sb_info; +}; + +struct index_node +{ + unsigned long file_size; + unsigned long blocks; + unsigned long attribute; + + struct super_block * sb; + + struct file_operations * f_ops; + struct index_node_operations * inode_ops; + + void * private_index_info; +}; + +#define FS_ATTR_FILE (1UL << 0) +#define FS_ATTR_DIR (1UL << 1) +#define FS_ATTR_DEVICE (1UL << 2) + +struct dir_entry +{ + char * name; + int name_length; + struct List child_node; + struct List subdirs_list; + + struct index_node * dir_inode; + struct dir_entry * parent; + + struct dir_entry_operations * dir_ops; +}; + +struct file +{ + long position; + unsigned long mode; + + struct dir_entry * dentry; + + struct file_operations * f_ops; + + void * private_data; +}; + +struct super_block_operations +{ + void(*write_superblock)(struct super_block * sb); + void(*put_superblock)(struct super_block * sb); + + void(*write_inode)(struct index_node * inode); +}; + +struct index_node_operations +{ + long (*create)(struct index_node * inode,struct dir_entry * dentry,int mode); + struct dir_entry* (*lookup)(struct index_node * parent_inode,struct dir_entry * dest_dentry); + long (*mkdir)(struct index_node * inode,struct dir_entry * dentry,int mode); + long (*rmdir)(struct index_node * inode,struct dir_entry * dentry); + long (*rename)(struct index_node * old_inode,struct dir_entry * old_dentry,struct index_node * new_inode,struct dir_entry * new_dentry); + long (*getattr)(struct dir_entry * dentry,unsigned long * attr); + long (*setattr)(struct dir_entry * dentry,unsigned long * attr); +}; + +struct dir_entry_operations +{ + long (*compare)(struct dir_entry * parent_dentry,char * source_filename,char * destination_filename); + long (*hash)(struct dir_entry * dentry,char * filename); + long (*release)(struct dir_entry * dentry); + long (*iput)(struct dir_entry * dentry,struct index_node * inode); +}; + +typedef int (*filldir_t)(void *buf,char *name, long namelen,long type,long offset); + +struct file_operations +{ + long (*open)(struct index_node * inode,struct file * filp); + long (*close)(struct index_node * inode,struct file * filp); + long (*read)(struct file * filp,char * buf,unsigned long count,long * position); + long (*write)(struct file * filp,char * buf,unsigned long count,long * position); + long (*lseek)(struct file * filp,long offset,long origin); + long (*ioctl)(struct index_node * inode,struct file * filp,unsigned long cmd,unsigned long arg); + + long (*readdir)(struct file * filp,void * dirent,filldir_t filler); +}; + +struct dir_entry * path_walk(char * name,unsigned long flags); +int fill_dentry(void *buf,char *name, long namelen,long type,long offset); +extern struct super_block * root_sb; + +#endif diff --git a/kernel/atomic.h b/kernel/atomic.h new file mode 100644 index 0000000000000000000000000000000000000000..ff22ceb6c1de0051b0c3a99d25bce78dbfdb1604 --- /dev/null +++ b/kernel/atomic.h @@ -0,0 +1,76 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __ATOMIC_H__ + +#define __ATOMIC_H__ + +typedef struct +{ + __volatile__ long value; +} atomic_T; + +#define atomic_read(atomic) ((atomic)->value) +#define atomic_set(atomic,val) (((atomic)->value) = (val)) + +inline void atomic_add(atomic_T * atomic,long value) +{ + __asm__ __volatile__ ( "lock addq %1, %0 \n\t" + :"=m"(atomic->value) + :"r"(value) + :"memory" + ); +} + +inline void atomic_sub(atomic_T *atomic,long value) +{ + __asm__ __volatile__ ( "lock subq %1, %0 \n\t" + :"=m"(atomic->value) + :"r"(value) + :"memory" + ); +} + +inline void atomic_inc(atomic_T *atomic) +{ + __asm__ __volatile__ ( "lock incq %0 \n\t" + :"=m"(atomic->value) + :"m"(atomic->value) + :"memory" + ); +} + +inline void atomic_dec(atomic_T *atomic) +{ + __asm__ __volatile__ ( "lock decq %0 \n\t" + :"=m"(atomic->value) + :"m"(atomic->value) + :"memory" + ); +} + +inline void atomic_set_mask(atomic_T *atomic,long mask) +{ + __asm__ __volatile__ ( "lock orq %1, %0 \n\t" + :"=m"(atomic->value) + :"r"(mask) + :"memory" + ); +} + +inline void atomic_clear_mask(atomic_T *atomic,long mask) +{ + __asm__ __volatile__ ( "lock andq %1, %0 \n\t" + :"=m"(atomic->value) + :"r"(~(mask)) + :"memory" + ); +} + +#endif diff --git a/kernel/backtrace.c b/kernel/backtrace.c new file mode 100644 index 0000000000000000000000000000000000000000..3c963ddb43bf51a2438961bad64755784c1ac7e4 --- /dev/null +++ b/kernel/backtrace.c @@ -0,0 +1,51 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "backtrace.h" +#include "printk.h" + +extern unsigned long kallsyms_addresses[] __attribute__((weak));; +extern long kallsyms_syms_num __attribute__((weak));; +extern long kallsyms_index[] __attribute__((weak));; +extern char* kallsyms_names __attribute__((weak));; + +int lookup_kallsyms(unsigned long address) +{ + int index = 0; + char * string =(char *) &kallsyms_names; + for(index = 0;index kallsyms_addresses[index] && address <= kallsyms_addresses[index+1]) + break; + if(index < kallsyms_syms_num) + { + color_printk(WHITE,BLUE,"backtrace address:%#018lx (+) %04d\tbacktrace function:%s(%#018lx)\n",address,address - kallsyms_addresses[index],&string[kallsyms_index[index]],kallsyms_addresses[index]); + return 0; + } + else + return 1; +} + +void backtrace(struct pt_regs * regs) +{ + unsigned long *rbp = (unsigned long *)regs->rbp; + unsigned long ret_address = *(rbp+1); + int i = 0; + + lookup_kallsyms(regs->rip); + for(i = 0;i<10;i++) + { + if(lookup_kallsyms(ret_address)) + break; + rbp = (unsigned long *)*rbp; + ret_address = *(rbp+1); + } +} + + + diff --git a/kernel/backtrace.h b/kernel/backtrace.h new file mode 100644 index 0000000000000000000000000000000000000000..72d56a760783ca5c1d7d578b1def2a94d0cb1321 --- /dev/null +++ b/kernel/backtrace.h @@ -0,0 +1,18 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __BACKTRACE_H__ + +#define __BACKTRACE_H__ + +#include "ptrace.h" + +void backtrace(struct pt_regs * regs); + +#endif diff --git a/kernel/block.h b/kernel/block.h new file mode 100644 index 0000000000000000000000000000000000000000..168225a5f3d4474f564177f734f95fea73fe5113 --- /dev/null +++ b/kernel/block.h @@ -0,0 +1,24 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __BLOCK_H__ + +#define __BLOCK_H__ + + + +struct block_device_operation +{ + long (* open)(); + long (* close)(); + long (* ioctl)(long cmd,long arg); + long (* transfer)(long cmd,unsigned long blocks,long count,unsigned char * buffer); +}; + +#endif diff --git a/kernel/cpu.c b/kernel/cpu.c new file mode 100644 index 0000000000000000000000000000000000000000..24ac628bc3f3d9e4ac918c4e0dcd3f3e50220c01 --- /dev/null +++ b/kernel/cpu.c @@ -0,0 +1,69 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "cpu.h" +#include "printk.h" + +/* + +*/ + +void init_cpu(void) +{ + int i; + unsigned int CpuFacName[4] = {0,0,0,0}; + char FactoryName[17] = {0}; + + //vendor_string + get_cpuid(0,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]); + + *(unsigned int*)&FactoryName[0] = CpuFacName[1]; + + *(unsigned int*)&FactoryName[4] = CpuFacName[3]; + + *(unsigned int*)&FactoryName[8] = CpuFacName[2]; + + FactoryName[12] = '\0'; + color_printk(YELLOW,BLACK,"%s\t%#010x\t%#010x\t%#010x\n",FactoryName,CpuFacName[1],CpuFacName[3],CpuFacName[2]); + + //brand_string + for(i = 0x80000002;i < 0x80000005;i++) + { + get_cpuid(i,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]); + + *(unsigned int*)&FactoryName[0] = CpuFacName[0]; + + *(unsigned int*)&FactoryName[4] = CpuFacName[1]; + + *(unsigned int*)&FactoryName[8] = CpuFacName[2]; + + *(unsigned int*)&FactoryName[12] = CpuFacName[3]; + + FactoryName[16] = '\0'; + color_printk(YELLOW,BLACK,"%s",FactoryName); + } + color_printk(YELLOW,BLACK,"\n"); + + //Version Informatin Type,Family,Model,and Stepping ID + get_cpuid(1,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]); + color_printk(YELLOW,BLACK,"Family Code:%#010x,Extended Family:%#010x,Model Number:%#010x,Extended Model:%#010x,Processor Type:%#010x,Stepping ID:%#010x\n",(CpuFacName[0] >> 8 & 0xf),(CpuFacName[0] >> 20 & 0xff),(CpuFacName[0] >> 4 & 0xf),(CpuFacName[0] >> 16 & 0xf),(CpuFacName[0] >> 12 & 0x3),(CpuFacName[0] & 0xf)); + + //get Linear/Physical Address size + get_cpuid(0x80000008,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]); + color_printk(YELLOW,BLACK,"Physical Address size:%08d,Linear Address size:%08d\n",(CpuFacName[0] & 0xff),(CpuFacName[0] >> 8 & 0xff)); + + //max cpuid operation code + get_cpuid(0,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]); + color_printk(WHITE,BLACK,"MAX Basic Operation Code :%#010x\t",CpuFacName[0]); + + get_cpuid(0x80000000,0,&CpuFacName[0],&CpuFacName[1],&CpuFacName[2],&CpuFacName[3]); + color_printk(WHITE,BLACK,"MAX Extended Operation Code :%#010x\n",CpuFacName[0]); + + +} diff --git a/kernel/cpu.h b/kernel/cpu.h index 0d7304486b5fb2b4aae8454d39a4537e83297bd7..e397bc62487426511dd49c0683d256129664968a 100644 --- a/kernel/cpu.h +++ b/kernel/cpu.h @@ -11,7 +11,24 @@ #define __CPU_H__ - #define NR_CPUS 8 +/* + +*/ + +inline void get_cpuid(unsigned int Mop,unsigned int Sop,unsigned int * a,unsigned int * b,unsigned int * c,unsigned int * d) +{ + __asm__ __volatile__ ( "cpuid \n\t" + :"=a"(*a),"=b"(*b),"=c"(*c),"=d"(*d) + :"0"(Mop),"2"(Sop) + ); +} + +/* + +*/ + +void init_cpu(void); + #endif diff --git a/kernel/dirent.h b/kernel/dirent.h new file mode 100644 index 0000000000000000000000000000000000000000..2a090a277f535ff87c50e02c5d227192b35a3469 --- /dev/null +++ b/kernel/dirent.h @@ -0,0 +1,23 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __DIRENT_H__ + +#define __DIRENT_H__ + +struct dirent +{ + long d_offset; + long d_type; + long d_namelen; + char d_name[]; +}; + + +#endif diff --git a/kernel/disk.c b/kernel/disk.c new file mode 100644 index 0000000000000000000000000000000000000000..dc0f0687df93fecb69fedbe157c40701e6aa972a --- /dev/null +++ b/kernel/disk.c @@ -0,0 +1,319 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "disk.h" +#include "APIC.h" +#include "memory.h" +#include "printk.h" +#include "lib.h" +#include "block.h" +#include "semaphore.h" + +static int disk_flags = 0; + +struct request_queue disk_request; + +struct block_device_operation IDE_device_operation; + +void end_request(struct block_buffer_node * node) +{ + if(node == NULL) + color_printk(RED,BLACK,"end_request error\n"); + + node->wait_queue.tsk->state = TASK_RUNNING; + insert_task_queue(node->wait_queue.tsk); +// node->wait_queue.tsk->flags |= NEED_SCHEDULE; + current->flags |= NEED_SCHEDULE; + + kfree((unsigned long *)disk_request.in_using); + disk_request.in_using = NULL; + + if(disk_request.block_request_count) + cmd_out(); +} + +void add_request(struct block_buffer_node * node) +{ + list_add_to_before(&disk_request.wait_queue_list.wait_list,&node->wait_queue.wait_list); + disk_request.block_request_count++; +} + +long cmd_out() +{ + wait_queue_T *wait_queue_tmp = container_of(list_next(&disk_request.wait_queue_list.wait_list),wait_queue_T,wait_list); + struct block_buffer_node * node = disk_request.in_using = container_of(wait_queue_tmp,struct block_buffer_node,wait_queue); + list_del(&disk_request.in_using->wait_queue.wait_list); + disk_request.block_request_count--; + + while(io_in8(PORT_DISK1_STATUS_CMD) & DISK_STATUS_BUSY) + nop(); + + switch(node->cmd) + { + case ATA_WRITE_CMD: + + io_out8(PORT_DISK1_DEVICE,0x40); + + io_out8(PORT_DISK1_ERR_FEATURE,0); + io_out8(PORT_DISK1_SECTOR_CNT,(node->count >> 8) & 0xff); + io_out8(PORT_DISK1_SECTOR_LOW ,(node->LBA >> 24) & 0xff); + io_out8(PORT_DISK1_SECTOR_MID ,(node->LBA >> 32) & 0xff); + io_out8(PORT_DISK1_SECTOR_HIGH,(node->LBA >> 40) & 0xff); + + io_out8(PORT_DISK1_ERR_FEATURE,0); + io_out8(PORT_DISK1_SECTOR_CNT,node->count & 0xff); + io_out8(PORT_DISK1_SECTOR_LOW,node->LBA & 0xff); + io_out8(PORT_DISK1_SECTOR_MID,(node->LBA >> 8) & 0xff); + io_out8(PORT_DISK1_SECTOR_HIGH,(node->LBA >> 16) & 0xff); + + while(!(io_in8(PORT_DISK1_STATUS_CMD) & DISK_STATUS_READY)) + nop(); + io_out8(PORT_DISK1_STATUS_CMD,node->cmd); + + while(!(io_in8(PORT_DISK1_STATUS_CMD) & DISK_STATUS_REQ)) + nop(); + port_outsw(PORT_DISK1_DATA,node->buffer,256); + break; + + case ATA_READ_CMD: + + io_out8(PORT_DISK1_DEVICE,0x40); + + io_out8(PORT_DISK1_ERR_FEATURE,0); + io_out8(PORT_DISK1_SECTOR_CNT,(node->count >> 8) & 0xff); + io_out8(PORT_DISK1_SECTOR_LOW ,(node->LBA >> 24) & 0xff); + io_out8(PORT_DISK1_SECTOR_MID ,(node->LBA >> 32) & 0xff); + io_out8(PORT_DISK1_SECTOR_HIGH,(node->LBA >> 40) & 0xff); + + io_out8(PORT_DISK1_ERR_FEATURE,0); + io_out8(PORT_DISK1_SECTOR_CNT,node->count & 0xff); + io_out8(PORT_DISK1_SECTOR_LOW,node->LBA & 0xff); + io_out8(PORT_DISK1_SECTOR_MID,(node->LBA >> 8) & 0xff); + io_out8(PORT_DISK1_SECTOR_HIGH,(node->LBA >> 16) & 0xff); + + while(!(io_in8(PORT_DISK1_STATUS_CMD) & DISK_STATUS_READY)) + nop(); + io_out8(PORT_DISK1_STATUS_CMD,node->cmd); + break; + + case GET_IDENTIFY_DISK_CMD: + + io_out8(PORT_DISK1_DEVICE,0xe0); + + io_out8(PORT_DISK1_ERR_FEATURE,0); + io_out8(PORT_DISK1_SECTOR_CNT,node->count & 0xff); + io_out8(PORT_DISK1_SECTOR_LOW,node->LBA & 0xff); + io_out8(PORT_DISK1_SECTOR_MID,(node->LBA >> 8) & 0xff); + io_out8(PORT_DISK1_SECTOR_HIGH,(node->LBA >> 16) & 0xff); + + while(!(io_in8(PORT_DISK1_STATUS_CMD) & DISK_STATUS_READY)) + nop(); + io_out8(PORT_DISK1_STATUS_CMD,node->cmd); + + default: + color_printk(BLACK,WHITE,"ATA CMD Error\n"); + break; + } + return 1; +} + +void read_handler(unsigned long nr, unsigned long parameter) +{ + struct block_buffer_node * node = ((struct request_queue *)parameter)->in_using; + + if(io_in8(PORT_DISK1_STATUS_CMD) & DISK_STATUS_ERROR) + color_printk(RED,BLACK,"read_handler:%#010x\n",io_in8(PORT_DISK1_ERR_FEATURE)); + else + port_insw(PORT_DISK1_DATA,node->buffer,256); + + node->count--; + if(node->count) + { + node->buffer += 512; + return; + } + + end_request(node); +} + +void write_handler(unsigned long nr, unsigned long parameter) +{ + struct block_buffer_node * node = ((struct request_queue *)parameter)->in_using; + + if(io_in8(PORT_DISK1_STATUS_CMD) & DISK_STATUS_ERROR) + color_printk(RED,BLACK,"write_handler:%#010x\n",io_in8(PORT_DISK1_ERR_FEATURE)); + + node->count--; + if(node->count) + { + node->buffer += 512; + while(!(io_in8(PORT_DISK1_STATUS_CMD) & DISK_STATUS_REQ)) + nop(); + port_outsw(PORT_DISK1_DATA,node->buffer,256); + return; + } + + end_request(node); +} + +void other_handler(unsigned long nr, unsigned long parameter) +{ + struct block_buffer_node * node = ((struct request_queue *)parameter)->in_using; + + if(io_in8(PORT_DISK1_STATUS_CMD) & DISK_STATUS_ERROR) + color_printk(RED,BLACK,"other_handler:%#010x\n",io_in8(PORT_DISK1_ERR_FEATURE)); + else + port_insw(PORT_DISK1_DATA,node->buffer,256); + + end_request(node); +} + +struct block_buffer_node * make_request(long cmd,unsigned long blocks,long count,unsigned char * buffer) +{ + struct block_buffer_node * node = (struct block_buffer_node *)kmalloc(sizeof(struct block_buffer_node),0); + wait_queue_init(&node->wait_queue,current); + + switch(cmd) + { + case ATA_READ_CMD: + node->end_handler = read_handler; + node->cmd = ATA_READ_CMD; + break; + + case ATA_WRITE_CMD: + node->end_handler = write_handler; + node->cmd = ATA_WRITE_CMD; + break; + + default:/// + node->end_handler = other_handler; + node->cmd = cmd; + break; + } + + node->LBA = blocks; + node->count = count; + node->buffer = buffer; + + return node; +} + +void submit(struct block_buffer_node * node) +{ + add_request(node); + + if(disk_request.in_using == NULL) + cmd_out(); +} + +void wait_for_finish() +{ + current->state = TASK_UNINTERRUPTIBLE; + schedule(); +} + +long IDE_open() +{ + color_printk(BLACK,WHITE,"DISK1 Opened\n"); + return 1; +} + +long IDE_close() +{ + color_printk(BLACK,WHITE,"DISK1 Closed\n"); + return 1; +} + +long IDE_ioctl(long cmd,long arg) +{ + struct block_buffer_node * node = NULL; + + if(cmd == GET_IDENTIFY_DISK_CMD) + { + node = make_request(cmd,0,0,(unsigned char *)arg); + submit(node); + wait_for_finish(); + return 1; + } + + return 0; +} + +long IDE_transfer(long cmd,unsigned long blocks,long count,unsigned char * buffer) +{ + struct block_buffer_node * node = NULL; + if(cmd == ATA_READ_CMD || cmd == ATA_WRITE_CMD) + { + node = make_request(cmd,blocks,count,buffer); + submit(node); + wait_for_finish(); + } + else + { + return 0; + } + + return 1; +} + +struct block_device_operation IDE_device_operation = +{ + .open = IDE_open, + .close = IDE_close, + .ioctl = IDE_ioctl, + .transfer = IDE_transfer, +}; + +hw_int_controller disk_int_controller = +{ + .enable = IOAPIC_enable, + .disable = IOAPIC_disable, + .install = IOAPIC_install, + .uninstall = IOAPIC_uninstall, + .ack = IOAPIC_edge_ack, +}; + +void disk_handler(unsigned long nr, unsigned long parameter, struct pt_regs * regs) +{ + struct block_buffer_node * node = ((struct request_queue *)parameter)->in_using; +// color_printk(BLACK,WHITE,"disk_handler,preempt:%d,pid:%d,cRSP:%#018lx,RSP:%#018lx,RIP:%#018lx\n",current->preempt_count,current->pid,get_rsp(),regs->rsp,regs->rip); + node->end_handler(nr,parameter); +} + +void disk_init() +{ + struct IO_APIC_RET_entry entry; + + entry.vector = 0x2f; + entry.deliver_mode = APIC_ICR_IOAPIC_Fixed ; + entry.dest_mode = ICR_IOAPIC_DELV_PHYSICAL; + entry.deliver_status = APIC_ICR_IOAPIC_Idle; + entry.polarity = APIC_IOAPIC_POLARITY_HIGH; + entry.irr = APIC_IOAPIC_IRR_RESET; + entry.trigger = APIC_ICR_IOAPIC_Edge; + entry.mask = APIC_ICR_IOAPIC_Masked; + entry.reserved = 0; + + entry.destination.physical.reserved1 = 0; + entry.destination.physical.phy_dest = 0; + entry.destination.physical.reserved2 = 0; + + register_irq(0x2f, &entry , &disk_handler, (unsigned long)&disk_request, &disk_int_controller, "disk1"); + + io_out8(PORT_DISK1_ALT_STA_CTL,0); + + wait_queue_init(&disk_request.wait_queue_list,NULL); + disk_request.in_using = NULL; + disk_request.block_request_count = 0; +} + +void disk_exit() +{ + unregister_irq(0x2f); +} diff --git a/kernel/disk.h b/kernel/disk.h new file mode 100644 index 0000000000000000000000000000000000000000..7dc89e617b0bc45b4a407ac026927f6a6f765d47 --- /dev/null +++ b/kernel/disk.h @@ -0,0 +1,397 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __DISK_H__ + +#define __DISK_H__ + +#include "lib.h" +#include "block.h" +#include "semaphore.h" + +#define PORT_DISK0_DATA 0x1f0 +#define PORT_DISK0_ERR_FEATURE 0x1f1 +#define PORT_DISK0_SECTOR_CNT 0x1f2 +#define PORT_DISK0_SECTOR_LOW 0x1f3 +#define PORT_DISK0_SECTOR_MID 0x1f4 +#define PORT_DISK0_SECTOR_HIGH 0x1f5 +#define PORT_DISK0_DEVICE 0x1f6 +#define PORT_DISK0_STATUS_CMD 0x1f7 + +#define PORT_DISK0_ALT_STA_CTL 0x3f6 + + +#define PORT_DISK1_DATA 0x170 +#define PORT_DISK1_ERR_FEATURE 0x171 +#define PORT_DISK1_SECTOR_CNT 0x172 +#define PORT_DISK1_SECTOR_LOW 0x173 +#define PORT_DISK1_SECTOR_MID 0x174 +#define PORT_DISK1_SECTOR_HIGH 0x175 +#define PORT_DISK1_DEVICE 0x176 +#define PORT_DISK1_STATUS_CMD 0x177 + +#define PORT_DISK1_ALT_STA_CTL 0x376 + +#define DISK_STATUS_BUSY (1 << 7) +#define DISK_STATUS_READY (1 << 6) +#define DISK_STATUS_SEEK (1 << 4) +#define DISK_STATUS_REQ (1 << 3) +#define DISK_STATUS_ERROR (1 << 0) + +#define ATA_READ_CMD 0x24 +#define ATA_WRITE_CMD 0x34 +#define GET_IDENTIFY_DISK_CMD 0xEC + +struct block_buffer_node +{ + unsigned int count; + unsigned char cmd; + unsigned long LBA; + unsigned char * buffer; + void(* end_handler)(unsigned long nr, unsigned long parameter); + + wait_queue_T wait_queue; +}; + +struct request_queue +{ +// struct List queue_list; + wait_queue_T wait_queue_list; + struct block_buffer_node *in_using; + long block_request_count; +}; + +extern struct request_queue disk_request; + +extern struct block_device_operation IDE_device_operation; + + +struct Disk_Identify_Info +{ + // 0 General configuration bit-significant information + unsigned short General_Config; + + // 1 Obsolete + unsigned short Obsolete0; + + // 2 Specific configuration + unsigned short Specific_Coinfig; + + // 3 Obsolete + unsigned short Obsolete1; + + // 4-5 Retired + unsigned short Retired0[2]; + + // 6 Obsolete + unsigned short Obsolete2; + + // 7-8 Reserved for the CompactFlash Association + unsigned short CompactFlash[2]; + + // 9 Retired + unsigned short Retired1; + + // 10-19 Serial number (20 ASCII characters) + unsigned short Serial_Number[10]; + + // 20-21 Retired + unsigned short Retired2[2]; + + // 22 Obsolete + unsigned short Obsolete3; + + // 23-26 Firmware revision(8 ASCII characters) + unsigned short Firmware_Version[4]; + + // 27-46 Model number (40 ASCII characters) + unsigned short Model_Number[20]; + + // 47 15:8 80h + // 7:0 00h=Reserved + // 01h-FFh = Maximumnumber of logical sectors that shall be transferred per DRQ data block on READ/WRITE MULTIPLE commands + unsigned short Max_logical_transferred_per_DRQ; + + // 48 Trusted Computing feature set options + unsigned short Trusted_Computing_feature_set_options; + + // 49 Capabilities + unsigned short Capabilities0; + + // 50 Capabilities + unsigned short Capabilities1; + + // 51-52 Obsolete + unsigned short Obsolete4[2]; + + // 53 15:8 Free-fall Control Sensitivity + // 7:3 Reserved + // 2 the fields reported in word 88 are valid + // 1 the fields reported in words (70:64) are valid + unsigned short Report_88_70to64_valid; + + // 54-58 Obsolete + unsigned short Obsolete5[5]; + + // 59 15:9 Reserved + // 8 Multiple sector setting is valid + // 7:0 xxh current setting for number of logical sectors that shall be transferred per DRQ data block on READ/WRITE Multiple commands + unsigned short Mul_Sec_Setting_Valid; + + // 60-61 Total number of user addresssable logical sectors for 28bit CMD + unsigned short Addressable_Logical_Sectors_for_28[2]; + + // 62 Obsolete + unsigned short Obsolete6; + + // 63 15:11 Reserved + // 10:8=1 Multiword DMA mode 210 is selected + // 7:3 Reserved + // 2:0=1 Multiword DMA mode 210 and below are supported + unsigned short MultWord_DMA_Select; + + // 64 15:8 Reserved + // 7:0 PIO mdoes supported + unsigned short PIO_mode_supported; + + // 65 Minimum Multiword DMA transfer cycle time per word + unsigned short Min_MulWord_DMA_cycle_time_per_word; + + // 66 Manufacturer`s recommended Multiword DMA transfer cycle time + unsigned short Manufacture_Recommend_MulWord_DMA_cycle_time; + + // 67 Minimum PIO transfer cycle time without flow control + unsigned short Min_PIO_cycle_time_Flow_Control; + + // 68 Minimum PIO transfer cycle time with IORDY flow control + unsigned short Min_PIO_cycle_time_IOREDY_Flow_Control; + + // 69-70 Reserved + unsigned short Reserved1[2]; + + // 71-74 Reserved for the IDENTIFY PACKET DEVICE command + unsigned short Reserved2[4]; + + // 75 Queue depth + unsigned short Queue_depth; + + // 76 Serial ATA Capabilities + unsigned short SATA_Capabilities; + + // 77 Reserved for Serial ATA + unsigned short Reserved3; + + // 78 Serial ATA features Supported + unsigned short SATA_features_Supported; + + // 79 Serial ATA features enabled + unsigned short SATA_features_enabled; + + // 80 Major Version number + unsigned short Major_Version; + + // 81 Minor version number + unsigned short Minor_Version; + + // 82 Commands and feature sets supported + unsigned short Cmd_feature_sets_supported0; + + // 83 Commands and feature sets supported + unsigned short Cmd_feature_sets_supported1; + + // 84 Commands and feature sets supported + unsigned short Cmd_feature_sets_supported2; + + // 85 Commands and feature sets supported or enabled + unsigned short Cmd_feature_sets_supported3; + + // 86 Commands and feature sets supported or enabled + unsigned short Cmd_feature_sets_supported4; + + // 87 Commands and feature sets supported or enabled + unsigned short Cmd_feature_sets_supported5; + + // 88 15 Reserved + // 14:8=1 Ultra DMA mode 6543210 is selected + // 7 Reserved + // 6:0=1 Ultra DMA mode 6543210 and below are suported + unsigned short Ultra_DMA_modes; + + // 89 Time required for Normal Erase mode SECURITY ERASE UNIT command + unsigned short Time_required_Erase_CMD; + + // 90 Time required for an Enhanced Erase mode SECURITY ERASE UNIT command + unsigned short Time_required_Enhanced_CMD; + + // 91 Current APM level value + unsigned short Current_APM_level_Value; + + // 92 Master Password Identifier + unsigned short Master_Password_Identifier; + + // 93 Hardware resset result.The contents of bits (12:0) of this word shall change only during the execution of a hardware reset. + unsigned short HardWare_Reset_Result; + + // 94 Current AAM value + // 15:8 Vendor’s recommended AAM value + // 7:0 Current AAM value + unsigned short Current_AAM_value; + + // 95 Stream Minimum Request Size + unsigned short Stream_Min_Request_Size; + + // 96 Streaming Transger Time-DMA + unsigned short Streaming_Transger_time_DMA; + + // 97 Streaming Access Latency-DMA and PIO + unsigned short Streaming_Access_Latency_DMA_PIO; + + // 98-99 Streaming Performance Granularity (DWord) + unsigned short Streaming_Performance_Granularity[2]; + + // 100-103 Total Number of User Addressable Logical Sectors for 48-bit commands (QWord) + unsigned short Total_user_LBA_for_48_Address_Feature_set[4]; + + // 104 Streaming Transger Time-PIO + unsigned short Streaming_Transfer_Time_PIO; + + // 105 Reserved + unsigned short Reserved4; + + // 106 Physical Sector size/Logical Sector Size + unsigned short Physical_Logical_Sector_Size; + + // 107 Inter-seek delay for ISO-7779 acoustic testing in microseconds + unsigned short Inter_seek_delay; + + // 108-111 World wide name + unsigned short World_wide_name[4]; + + // 112-115 Reserved + unsigned short Reserved5[4]; + + // 116 Reserved for TLC + unsigned short Reserved6; + + // 117-118 Logical sector size (DWord) + unsigned short Words_per_Logical_Sector[2]; + + // 119 Commands and feature sets supported (Continued from words 84:82) + unsigned short CMD_feature_Supported; + + // 120 Commands and feature sets supported or enabled (Continued from words 87:85) + unsigned short CMD_feature_Supported_enabled; + + // 121-126 Reserved for expanded supported and enabled settings + unsigned short Reserved7[6]; + + // 127 Obsolete + unsigned short Obsolete7; + + // 128 Security status + unsigned short Security_Status; + + // 129-159 Vendor specific + unsigned short Vendor_Specific[31]; + + // 160 CFA power mode + unsigned short CFA_Power_mode; + + // 161-167 Reserved for the CompactFlash Association + unsigned short Reserved8[7]; + + // 168 Device Nominal Form Factor + unsigned short Dev_from_Factor; + + // 169-175 Reserved + unsigned short Reserved9[7]; + + // 176-205 Current media serial number (ATA string) + unsigned short Current_Media_Serial_Number[30]; + + // 206 SCT Command Transport + unsigned short SCT_Cmd_Transport; + + // 207-208 Reserved for CE-ATA + unsigned short Reserved10[2]; + + // 209 Alignment of logical blocks within a physical block + unsigned short Alignment_Logical_blocks_within_a_physical_block; + + // 210-211 Write-Read-Verify Sector Count Mode 3 (DWord) + unsigned short Write_Read_Verify_Sector_Count_Mode_3[2]; + + // 212-213 Write-Read-Verify Sector Count Mode 2 (DWord) + unsigned short Write_Read_Verify_Sector_Count_Mode_2[2]; + + // 214 NV Cache Capabilities + unsigned short NV_Cache_Capabilities; + + // 215-216 NV Cache Size in Logical Blocks (DWord) + unsigned short NV_Cache_Size[2]; + + // 217 Nominal media rotation rate + unsigned short Nominal_media_rotation_rate; + + // 218 Reserved + unsigned short Reserved11; + + // 219 NV Cache Options + unsigned short NV_Cache_Options; + + // 220 Write-Read-Verify feature set current mode + unsigned short Write_Read_Verify_feature_set_current_mode; + + // 221 Reserved + unsigned short Reserved12; + + // 222 Transport major version number. + // 0000h or ffffh = device does not report version + unsigned short Transport_Major_Version_Number; + + // 223 Transport Minor version number + unsigned short Transport_Minor_Version_Number; + + // 224-233 Reserved for CE-ATA + unsigned short Reserved13[10]; + + // 234 Minimum number of 512-byte data blocks per DOWNLOAD MICROCODE command for mode 03h + unsigned short Mini_blocks_per_CMD; + + // 235 Maximum number of 512-byte data blocks per DOWNLOAD MICROCODE command for mode 03h + unsigned short Max_blocks_per_CMD; + + // 236-254 Reserved + unsigned short Reserved14[19]; + + // 255 Integrity word + // 15:8 Checksum + // 7:0 Checksum Validity Indicator + unsigned short Integrity_word; +}__attribute__((packed)); + +/* + +*/ + +void disk_init(); + +void disk_exit(); + +void write_handler(unsigned long nr, unsigned long parameter); +void read_handler(unsigned long nr, unsigned long parameter); +void other_handler(unsigned long nr, unsigned long parameter); + +struct block_buffer_node * make_request(long cmd,unsigned long blocks,long count,unsigned char * buffer); +void add_request(struct block_buffer_node * node); +long cmd_out(); +void end_request(); + + +#endif diff --git a/kernel/entry.S b/kernel/entry.S index 88df330348ec211ec37e436ab641ee16009e9ce8..fc520b879bd3b7b65f2f7caae70b9fbfbfdd1a9c 100644 --- a/kernel/entry.S +++ b/kernel/entry.S @@ -34,37 +34,70 @@ RFLAGS = 0xa8 OLDRSP = 0xb0 OLDSS = 0xb8 +////struct task_struct member offset +TSK_STATE = 0x00 +TSK_FLAGS = 0x08 +TSK_PREEMPT = 0x10 +TSK_SIGNAL = 0x18 + + RESTORE_ALL: - popq %r15; - popq %r14; - popq %r13; - popq %r12; - popq %r11; - popq %r10; - popq %r9; - popq %r8; - popq %rbx; - popq %rcx; - popq %rdx; - popq %rsi; - popq %rdi; - popq %rbp; - popq %rax; - movq %rax, %ds; - popq %rax; - movq %rax, %es; - popq %rax; - addq $0x10, %rsp; - iretq; + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %r11 + popq %r10 + popq %r9 + popq %r8 + popq %rbx + popq %rcx + popq %rdx + popq %rsi + popq %rdi + popq %rbp + popq %rax + movq %rax, %ds + popq %rax + movq %rax, %es + popq %rax + addq $0x10, %rsp + iretq #define GET_CURRENT(reg) \ movq $-32768,reg; \ andq %rsp, reg ret_from_exception: - /*GET_CURRENT(%ebx) need rewrite*/ + ENTRY(ret_from_intr) - jmp RESTORE_ALL /*need rewrite*/ + movq $-1, %rcx + testq softirq_status(%rip), %rcx ////check softirq + jnz softirq_handler + GET_CURRENT(%rbx) + movq TSK_PREEMPT(%rbx), %rcx ////check preempt + cmpq $0, %rcx + jne RESTORE_ALL + movq TSK_FLAGS(%rbx), %rcx ////try schedule + testq $2, %rcx + jnz reschedule + jmp RESTORE_ALL + +softirq_handler: + callq do_softirq + GET_CURRENT(%rbx) + movq TSK_PREEMPT(%rbx), %rcx ////check preempt + cmpq $0, %rcx + jne RESTORE_ALL + movq TSK_FLAGS(%rbx), %rcx ////try schedule + testq $2, %rcx + jnz reschedule + jmp RESTORE_ALL + +reschedule: + callq schedule ////do schedule + jmp RESTORE_ALL + ENTRY(system_call) sti @@ -160,11 +193,11 @@ error_code: pushq %r12 pushq %r13 pushq %r14 - pushq %r15 - + pushq %r15 + cld movq ERRCODE(%rsp), %rsi - movq FUNC(%rsp), %rdx + movq FUNC(%rsp), %rdx movq $0x10, %rdi movq %rdi, %ds @@ -175,7 +208,7 @@ error_code: callq *%rdx - jmp ret_from_exception + jmp ret_from_exception ENTRY(debug) pushq $0 @@ -186,35 +219,35 @@ ENTRY(debug) ENTRY(nmi) pushq %rax - cld; - pushq %rax; - + cld; + pushq %rax + pushq %rax movq %es, %rax pushq %rax movq %ds, %rax pushq %rax xorq %rax, %rax - - pushq %rbp; - pushq %rdi; - pushq %rsi; - pushq %rdx; - pushq %rcx; - pushq %rbx; - pushq %r8; - pushq %r9; - pushq %r10; - pushq %r11; - pushq %r12; - pushq %r13; - pushq %r14; - pushq %r15; - - movq $0x10, %rdx; - movq %rdx, %ds; - movq %rdx, %es; - + + pushq %rbp + pushq %rdi + pushq %rsi + pushq %rdx + pushq %rcx + pushq %rbx + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + + movq $0x10, %rdx + movq %rdx, %ds + movq %rdx, %es + movq $0, %rsi movq %rsp, %rdi diff --git a/kernel/errno.h b/kernel/errno.h index d5de3dd277573e607d1598cbf13d561278729e13..5fa934aaba3fab661d6bf9c54706d082c10b8e52 100644 --- a/kernel/errno.h +++ b/kernel/errno.h @@ -1,5 +1,5 @@ /*************************************************** -* Copyright (c) 2018 MINE ÌïÓî +* Copyright (c) 2018 MINE 田宇 * * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public @@ -103,4 +103,4 @@ immediately established */ -#endif \ No newline at end of file +#endif diff --git a/kernel/fat32.c b/kernel/fat32.c new file mode 100644 index 0000000000000000000000000000000000000000..ca660147f437d1136d9af21bc5f4b8c52618695b --- /dev/null +++ b/kernel/fat32.c @@ -0,0 +1,860 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "fat32.h" +#include "disk.h" +#include "printk.h" +#include "lib.h" +#include "VFS.h" +#include "errno.h" +#include "stdio.h" + +unsigned int DISK1_FAT32_read_FAT_Entry(struct FAT32_sb_info * fsbi,unsigned int fat_entry) +{ + unsigned int buf[128]; + memset(buf,0,512); + IDE_device_operation.transfer(ATA_READ_CMD,fsbi->FAT1_firstsector + (fat_entry >> 7),1,(unsigned char *)buf); + color_printk(BLUE,BLACK,"DISK1_FAT32_read_FAT_Entry fat_entry:%#018lx,%#010x\n",fat_entry,buf[fat_entry & 0x7f]); + return buf[fat_entry & 0x7f] & 0x0fffffff; +} + + +unsigned long DISK1_FAT32_write_FAT_Entry(struct FAT32_sb_info * fsbi,unsigned int fat_entry,unsigned int value) +{ + unsigned int buf[128]; + int i; + + memset(buf,0,512); + IDE_device_operation.transfer(ATA_READ_CMD,fsbi->FAT1_firstsector + (fat_entry >> 7),1,(unsigned char *)buf); + buf[fat_entry & 0x7f] = (buf[fat_entry & 0x7f] & 0xf0000000) | (value & 0x0fffffff); + + for(i = 0;i < fsbi->NumFATs;i++) + IDE_device_operation.transfer(ATA_WRITE_CMD,fsbi->FAT1_firstsector + fsbi->sector_per_FAT * i + (fat_entry >> 7),1,(unsigned char *)buf); + return 1; +} + + +long FAT32_open(struct index_node * inode,struct file * filp) +{ + return 1; +} + + +long FAT32_close(struct index_node * inode,struct file * filp) +{ + return 1; +} + + +long FAT32_read(struct file * filp,char * buf,unsigned long count,long * position) +{ + struct FAT32_inode_info * finode = filp->dentry->dir_inode->private_index_info; + struct FAT32_sb_info * fsbi = filp->dentry->dir_inode->sb->private_sb_info; + + unsigned long cluster = finode->first_cluster; + unsigned long sector = 0; + int i,length = 0; + long retval = 0; + int index = *position / fsbi->bytes_per_cluster; + long offset = *position % fsbi->bytes_per_cluster; + char * buffer = (char *)kmalloc(fsbi->bytes_per_cluster,0); + + if(!cluster) + return -EFAULT; + for(i = 0;i < index;i++) + cluster = DISK1_FAT32_read_FAT_Entry(fsbi,cluster); + + if(*position + count > filp->dentry->dir_inode->file_size) + index = count = filp->dentry->dir_inode->file_size - *position; + else + index = count; + + color_printk(GREEN,BLACK,"FAT32_read first_cluster:%d,size:%d,preempt_count:%d\n",finode->first_cluster,filp->dentry->dir_inode->file_size,current->preempt_count); + + do + { + memset(buffer,0,fsbi->bytes_per_cluster); + sector = fsbi->Data_firstsector + (cluster - 2) * fsbi->sector_per_cluster; + if(!IDE_device_operation.transfer(ATA_READ_CMD,sector,fsbi->sector_per_cluster,(unsigned char *)buffer)) + { + color_printk(RED,BLACK,"FAT32 FS(read) read disk ERROR!!!!!!!!!!\n"); + retval = -EIO; + break; + } + + length = index <= fsbi->bytes_per_cluster - offset ? index : fsbi->bytes_per_cluster - offset; + + if((unsigned long)buf < TASK_SIZE) + copy_to_user(buffer + offset,buf,length); + else + memcpy(buffer + offset,buf,length); + + index -= length; + buf += length; + offset -= offset; + *position += length; + }while(index && (cluster = DISK1_FAT32_read_FAT_Entry(fsbi,cluster))); + + kfree(buffer); + if(!index) + retval = count; + return retval; +} + + +unsigned long FAT32_find_available_cluster(struct FAT32_sb_info * fsbi) +{ + int i,j; + int fat_entry; + unsigned long sector_per_fat = fsbi->sector_per_FAT; + unsigned int buf[128]; + +// fsbi->fat_fsinfo->FSI_Free_Count & fsbi->fat_fsinfo->FSI_Nxt_Free not exactly,so unuse + + for(i = 0;i < sector_per_fat;i++) + { + memset(buf,0,512); + IDE_device_operation.transfer(ATA_READ_CMD,fsbi->FAT1_firstsector + i,1,(unsigned char *)buf); + + for(j = 0;j < 128;j++) + { + if((buf[j] & 0x0fffffff) == 0) + return (i << 7) + j; + } + } + return 0; +} + + +long FAT32_write(struct file * filp,char * buf,unsigned long count,long * position) +{ + struct FAT32_inode_info * finode = filp->dentry->dir_inode->private_index_info; + struct FAT32_sb_info * fsbi = filp->dentry->dir_inode->sb->private_sb_info; + + unsigned long cluster = finode->first_cluster; + unsigned long next_cluster = 0; + unsigned long sector = 0; + int i,length = 0; + long retval = 0; + long flags = 0; + int index = *position / fsbi->bytes_per_cluster; + long offset = *position % fsbi->bytes_per_cluster; + char * buffer = (char *)kmalloc(fsbi->bytes_per_cluster,0); + + if(!cluster) + { + cluster = FAT32_find_available_cluster(fsbi); + flags = 1; + } + else + for(i = 0;i < index;i++) + cluster = DISK1_FAT32_read_FAT_Entry(fsbi,cluster); + + if(!cluster) + { + kfree(buffer); + return -ENOSPC; + } + + if(flags) + { + finode->first_cluster = cluster; + filp->dentry->dir_inode->sb->sb_ops->write_inode(filp->dentry->dir_inode); + DISK1_FAT32_write_FAT_Entry(fsbi,cluster,0x0ffffff8); + } + + index = count; + + do + { + if(!flags) + { + memset(buffer,0,fsbi->bytes_per_cluster); + sector = fsbi->Data_firstsector + (cluster - 2) * fsbi->sector_per_cluster; + if(!IDE_device_operation.transfer(ATA_READ_CMD,sector,fsbi->sector_per_cluster,(unsigned char *)buffer)) + { + color_printk(RED,BLACK,"FAT32 FS(write) read disk ERROR!!!!!!!!!!\n"); + retval = -EIO; + break; + } + } + + length = index <= fsbi->bytes_per_cluster - offset ? index : fsbi->bytes_per_cluster - offset; + + if((unsigned long)buf < TASK_SIZE) + copy_from_user(buf,buffer + offset,length); + else + memcpy(buf,buffer + offset,length); + + if(!IDE_device_operation.transfer(ATA_WRITE_CMD,sector,fsbi->sector_per_cluster,(unsigned char *)buffer)) + { + color_printk(RED,BLACK,"FAT32 FS(write) write disk ERROR!!!!!!!!!!\n"); + retval = -EIO; + break; + } + + index -= length; + buf += length; + offset -= offset; + *position += length; + + if(index) + next_cluster = DISK1_FAT32_read_FAT_Entry(fsbi,cluster); + else + break; + + if(next_cluster >= 0x0ffffff8) + { + next_cluster = FAT32_find_available_cluster(fsbi); + if(!next_cluster) + { + kfree(buffer); + return -ENOSPC; + } + + DISK1_FAT32_write_FAT_Entry(fsbi,cluster,next_cluster); + DISK1_FAT32_write_FAT_Entry(fsbi,next_cluster,0x0ffffff8); + cluster = next_cluster; + flags = 1; + } + + }while(index); + + if(*position > filp->dentry->dir_inode->file_size) + { + filp->dentry->dir_inode->file_size = *position; + filp->dentry->dir_inode->sb->sb_ops->write_inode(filp->dentry->dir_inode); + } + + kfree(buffer); + if(!index) + retval = count; + return retval; +} + + +long FAT32_lseek(struct file * filp,long offset,long origin) +{ + struct index_node *inode = filp->dentry->dir_inode; + long pos = 0; + + switch(origin) + { + case SEEK_SET: + pos = offset; + break; + + case SEEK_CUR: + pos = filp->position + offset; + break; + + case SEEK_END: + pos = filp->dentry->dir_inode->file_size + offset; + break; + + default: + return -EINVAL; + break; + } + + if(pos < 0 || pos > filp->dentry->dir_inode->file_size) + return -EOVERFLOW; + + filp->position = pos; + color_printk(GREEN,BLACK,"FAT32 FS(lseek) alert position:%d\n",filp->position); + + return pos; +} + + +long FAT32_ioctl(struct index_node * inode,struct file * filp,unsigned long cmd,unsigned long arg) +{} + +long FAT32_readdir(struct file * filp,void * dirent,filldir_t filler) +{ + struct FAT32_inode_info * finode = filp->dentry->dir_inode->private_index_info; + struct FAT32_sb_info * fsbi = filp->dentry->dir_inode->sb->private_sb_info; + + unsigned int cluster = 0; + unsigned long sector = 0; + unsigned char * buf =NULL; + char *name = NULL; + int namelen = 0; + int i = 0,j = 0,x = 0,y = 0; + struct FAT32_Directory * tmpdentry = NULL; + struct FAT32_LongDirectory * tmpldentry = NULL; + + buf = kmalloc(fsbi->bytes_per_cluster,0); + + cluster = finode->first_cluster; + + j = filp->position/fsbi->bytes_per_cluster; + + for(i = 0;i 0x0ffffff7) + { + color_printk(RED,BLACK,"FAT32 FS(readdir) cluster didn`t exist\n"); + return NULL; + } + } + +next_cluster: + sector = fsbi->Data_firstsector + (cluster - 2) * fsbi->sector_per_cluster; + if(!IDE_device_operation.transfer(ATA_READ_CMD,sector,fsbi->sector_per_cluster,(unsigned char *)buf)) + { + color_printk(RED,BLACK,"FAT32 FS(readdir) read disk ERROR!!!!!!!!!!\n"); + kfree(buf); + return NULL; + } + + tmpdentry = (struct FAT32_Directory *)(buf + filp->position%fsbi->bytes_per_cluster); + + for(i = filp->position%fsbi->bytes_per_cluster;i < fsbi->bytes_per_cluster;i += 32,tmpdentry++,filp->position += 32) + { + if(tmpdentry->DIR_Attr == ATTR_LONG_NAME) + continue; + if(tmpdentry->DIR_Name[0] == 0xe5 || tmpdentry->DIR_Name[0] == 0x00 || tmpdentry->DIR_Name[0] == 0x05) + continue; + + namelen = 0; + tmpldentry = (struct FAT32_LongDirectory *)tmpdentry-1; + + if(tmpldentry->LDIR_Attr == ATTR_LONG_NAME && tmpldentry->LDIR_Ord != 0xe5 && tmpldentry->LDIR_Ord != 0x00 && tmpldentry->LDIR_Ord != 0x05) + { + j = 0; + //long file/dir name read + while(tmpldentry->LDIR_Attr == ATTR_LONG_NAME && tmpldentry->LDIR_Ord != 0xe5 && tmpldentry->LDIR_Ord != 0x00 && tmpldentry->LDIR_Ord != 0x05) + { + j++; + if(tmpldentry->LDIR_Ord & 0x40) + break; + tmpldentry --; + } + + name = kmalloc(j*13+1,0); + memset(name,0,j*13+1); + tmpldentry = (struct FAT32_LongDirectory *)tmpdentry-1; + + for(x = 0;xLDIR_Name1[y] != 0xffff && tmpldentry->LDIR_Name1[y] != 0x0000) + name[namelen++] = (char)tmpldentry->LDIR_Name1[y]; + + for(y = 0;y<6;y++) + if(tmpldentry->LDIR_Name2[y] != 0xffff && tmpldentry->LDIR_Name2[y] != 0x0000) + name[namelen++] = (char)tmpldentry->LDIR_Name2[y]; + + for(y = 0;y<2;y++) + if(tmpldentry->LDIR_Name3[y] != 0xffff && tmpldentry->LDIR_Name3[y] != 0x0000) + name[namelen++] = (char)tmpldentry->LDIR_Name3[y]; + } + goto find_lookup_success; + } + + name = kmalloc(15,0); + memset(name,0,15); + //short file/dir base name compare + for(x=0;x<8;x++) + { + if(tmpdentry->DIR_Name[x] == ' ') + break; + if(tmpdentry->DIR_NTRes & LOWERCASE_BASE) + name[namelen++] = tmpdentry->DIR_Name[x] + 32; + else + name[namelen++] = tmpdentry->DIR_Name[x]; + } + + if(tmpdentry->DIR_Attr & ATTR_DIRECTORY) + goto find_lookup_success; + + name[namelen++] = '.'; + + //short file ext name compare + for(x=8;x<11;x++) + { + if(tmpdentry->DIR_Name[x] == ' ') + break; + if(tmpdentry->DIR_NTRes & LOWERCASE_EXT) + name[namelen++] = tmpdentry->DIR_Name[x] + 32; + else + name[namelen++] = tmpdentry->DIR_Name[x]; + } + if(x == 8) + name[--namelen] = 0; + goto find_lookup_success; + } + + cluster = DISK1_FAT32_read_FAT_Entry(fsbi,cluster); + if(cluster < 0x0ffffff7) + goto next_cluster; + + kfree(buf); + return NULL; + +find_lookup_success: + + filp->position += 32; + return filler(dirent,name,namelen,0,0); +} + + +struct file_operations FAT32_file_ops = +{ + .open = FAT32_open, + .close = FAT32_close, + .read = FAT32_read, + .write = FAT32_write, + .lseek = FAT32_lseek, + .ioctl = FAT32_ioctl, + + .readdir = FAT32_readdir, +}; + + +long FAT32_create(struct index_node * inode,struct dir_entry * dentry,int mode) +{} + + +struct dir_entry * FAT32_lookup(struct index_node * parent_inode,struct dir_entry * dest_dentry) +{ + struct FAT32_inode_info * finode = parent_inode->private_index_info; + struct FAT32_sb_info * fsbi = parent_inode->sb->private_sb_info; + + unsigned int cluster = 0; + unsigned long sector = 0; + unsigned char * buf =NULL; + int i = 0,j = 0,x = 0; + struct FAT32_Directory * tmpdentry = NULL; + struct FAT32_LongDirectory * tmpldentry = NULL; + struct index_node * p = NULL; + + buf = kmalloc(fsbi->bytes_per_cluster,0); + + cluster = finode->first_cluster; + +next_cluster: + sector = fsbi->Data_firstsector + (cluster - 2) * fsbi->sector_per_cluster; + color_printk(BLUE,BLACK,"lookup cluster:%#010x,sector:%#018lx\n",cluster,sector); + if(!IDE_device_operation.transfer(ATA_READ_CMD,sector,fsbi->sector_per_cluster,(unsigned char *)buf)) + { + color_printk(RED,BLACK,"FAT32 FS(lookup) read disk ERROR!!!!!!!!!!\n"); + kfree(buf); + return NULL; + } + + tmpdentry = (struct FAT32_Directory *)buf; + + for(i = 0;i < fsbi->bytes_per_cluster;i+= 32,tmpdentry++) + { + if(tmpdentry->DIR_Attr == ATTR_LONG_NAME) + continue; + if(tmpdentry->DIR_Name[0] == 0xe5 || tmpdentry->DIR_Name[0] == 0x00 || tmpdentry->DIR_Name[0] == 0x05) + continue; + + tmpldentry = (struct FAT32_LongDirectory *)tmpdentry-1; + j = 0; + + //long file/dir name compare + while(tmpldentry->LDIR_Attr == ATTR_LONG_NAME && tmpldentry->LDIR_Ord != 0xe5) + { + for(x=0;x<5;x++) + { + if(j>dest_dentry->name_length && tmpldentry->LDIR_Name1[x] == 0xffff) + continue; + else if(j>dest_dentry->name_length || tmpldentry->LDIR_Name1[x] != (unsigned short)(dest_dentry->name[j++])) + goto continue_cmp_fail; + } + for(x=0;x<6;x++) + { + if(j>dest_dentry->name_length && tmpldentry->LDIR_Name2[x] == 0xffff) + continue; + else if(j>dest_dentry->name_length || tmpldentry->LDIR_Name2[x] != (unsigned short)(dest_dentry->name[j++])) + goto continue_cmp_fail; + } + for(x=0;x<2;x++) + { + if(j>dest_dentry->name_length && tmpldentry->LDIR_Name3[x] == 0xffff) + continue; + else if(j>dest_dentry->name_length || tmpldentry->LDIR_Name3[x] != (unsigned short)(dest_dentry->name[j++])) + goto continue_cmp_fail; + } + + if(j >= dest_dentry->name_length) + { + goto find_lookup_success; + } + + tmpldentry --; + } + + //short file/dir base name compare + j = 0; + for(x=0;x<8;x++) + { + switch(tmpdentry->DIR_Name[x]) + { + case ' ': + if(!(tmpdentry->DIR_Attr & ATTR_DIRECTORY)) + { + if(dest_dentry->name[j]=='.') + continue; + else if(tmpdentry->DIR_Name[x] == dest_dentry->name[j]) + { + j++; + break; + } + else + goto continue_cmp_fail; + } + else + { + if(j < dest_dentry->name_length && tmpdentry->DIR_Name[x] == dest_dentry->name[j]) + { + j++; + break; + } + else if(j == dest_dentry->name_length) + continue; + else + goto continue_cmp_fail; + } + + case 'A' ... 'Z': + case 'a' ... 'z': + if(tmpdentry->DIR_NTRes & LOWERCASE_BASE) + if(j < dest_dentry->name_length && tmpdentry->DIR_Name[x] + 32 == dest_dentry->name[j]) + { + j++; + break; + } + else + goto continue_cmp_fail; + else + { + if(j < dest_dentry->name_length && tmpdentry->DIR_Name[x] == dest_dentry->name[j]) + { + j++; + break; + } + else + goto continue_cmp_fail; + } + + case '0' ... '9': + if(j < dest_dentry->name_length && tmpdentry->DIR_Name[x] == dest_dentry->name[j]) + { + j++; + break; + } + else + goto continue_cmp_fail; + + default : + j++; + break; + } + } + //short file ext name compare + if(!(tmpdentry->DIR_Attr & ATTR_DIRECTORY)) + { + j++; + for(x=8;x<11;x++) + { + switch(tmpdentry->DIR_Name[x]) + { + case 'A' ... 'Z': + case 'a' ... 'z': + if(tmpdentry->DIR_NTRes & LOWERCASE_EXT) + if(tmpdentry->DIR_Name[x] + 32 == dest_dentry->name[j]) + { + j++; + break; + } + else + goto continue_cmp_fail; + else + { + if(tmpdentry->DIR_Name[x] == dest_dentry->name[j]) + { + j++; + break; + } + else + goto continue_cmp_fail; + } + + case '0' ... '9': + if(tmpdentry->DIR_Name[x] == dest_dentry->name[j]) + { + j++; + break; + } + else + goto continue_cmp_fail; + + case ' ': + if(tmpdentry->DIR_Name[x] == dest_dentry->name[j]) + { + j++; + break; + } + else + goto continue_cmp_fail; + + default : + goto continue_cmp_fail; + } + } + } + goto find_lookup_success; + +continue_cmp_fail:; + } + + cluster = DISK1_FAT32_read_FAT_Entry(fsbi,cluster); + if(cluster < 0x0ffffff7) + goto next_cluster; + + kfree(buf); + return NULL; + +find_lookup_success: + p = (struct index_node *)kmalloc(sizeof(struct index_node),0); + memset(p,0,sizeof(struct index_node)); + p->file_size = tmpdentry->DIR_FileSize; + p->blocks = (p->file_size + fsbi->bytes_per_cluster - 1)/fsbi->bytes_per_sector; + p->attribute = (tmpdentry->DIR_Attr & ATTR_DIRECTORY) ? FS_ATTR_DIR : FS_ATTR_FILE; + p->sb = parent_inode->sb; + p->f_ops = &FAT32_file_ops; + p->inode_ops = &FAT32_inode_ops; + + p->private_index_info = (struct FAT32_inode_info *)kmalloc(sizeof(struct FAT32_inode_info),0); + memset(p->private_index_info,0,sizeof(struct FAT32_inode_info)); + finode = p->private_index_info; + + finode->first_cluster = (tmpdentry->DIR_FstClusHI<< 16 | tmpdentry->DIR_FstClusLO) & 0x0fffffff; + finode->dentry_location = cluster; + finode->dentry_position = tmpdentry - (struct FAT32_Directory *)buf; + finode->create_date = tmpdentry->DIR_CrtTime; + finode->create_time = tmpdentry->DIR_CrtDate; + finode->write_date = tmpdentry->DIR_WrtTime; + finode->write_time = tmpdentry->DIR_WrtDate; + + if((tmpdentry->DIR_FstClusHI >> 12) && (p->attribute & FS_ATTR_FILE)) + { + p->attribute |= FS_ATTR_DEVICE; + } + + dest_dentry->dir_inode = p; + kfree(buf); + return dest_dentry; +} + + +long FAT32_mkdir(struct index_node * inode,struct dir_entry * dentry,int mode) +{} + + +long FAT32_rmdir(struct index_node * inode,struct dir_entry * dentry) +{} + +long FAT32_rename(struct index_node * old_inode,struct dir_entry * old_dentry,struct index_node * new_inode,struct dir_entry * new_dentry) +{} + +long FAT32_getattr(struct dir_entry * dentry,unsigned long * attr) +{} + +long FAT32_setattr(struct dir_entry * dentry,unsigned long * attr) +{} + +struct index_node_operations FAT32_inode_ops = +{ + .create = FAT32_create, + .lookup = FAT32_lookup, + .mkdir = FAT32_mkdir, + .rmdir = FAT32_rmdir, + .rename = FAT32_rename, + .getattr = FAT32_getattr, + .setattr = FAT32_setattr, +}; + + +//// these operation need cache and list +long FAT32_compare(struct dir_entry * parent_dentry,char * source_filename,char * destination_filename){} +long FAT32_hash(struct dir_entry * dentry,char * filename){} +long FAT32_release(struct dir_entry * dentry){} +long FAT32_iput(struct dir_entry * dentry,struct index_node * inode){} + + +struct dir_entry_operations FAT32_dentry_ops = +{ + .compare = FAT32_compare, + .hash = FAT32_hash, + .release = FAT32_release, + .iput = FAT32_iput, +}; + + +void fat32_write_superblock(struct super_block * sb){} + +void fat32_put_superblock(struct super_block * sb) +{ + kfree(sb->private_sb_info); + kfree(sb->root->dir_inode->private_index_info); + kfree(sb->root->dir_inode); + kfree(sb->root); + kfree(sb); +} + +void fat32_write_inode(struct index_node * inode) +{ + struct FAT32_Directory * fdentry = NULL; + struct FAT32_Directory * buf = NULL; + struct FAT32_inode_info * finode = inode->private_index_info; + struct FAT32_sb_info * fsbi = inode->sb->private_sb_info; + unsigned long sector = 0; + + if(finode->dentry_location == 0) + { + color_printk(RED,BLACK,"FS ERROR:write root inode!\n"); + return ; + } + + sector = fsbi->Data_firstsector + (finode->dentry_location - 2) * fsbi->sector_per_cluster; + buf = (struct FAT32_Directory *)kmalloc(fsbi->bytes_per_cluster,0); + memset(buf,0,fsbi->bytes_per_cluster); + IDE_device_operation.transfer(ATA_READ_CMD,sector,fsbi->sector_per_cluster,(unsigned char *)buf); + fdentry = buf+finode->dentry_position; + + ////alert fat32 dentry data + fdentry->DIR_FileSize = inode->file_size; + fdentry->DIR_FstClusLO = finode->first_cluster & 0xffff; + fdentry->DIR_FstClusHI = (fdentry->DIR_FstClusHI & 0xf000) | (finode->first_cluster >> 16); + + IDE_device_operation.transfer(ATA_WRITE_CMD,sector,fsbi->sector_per_cluster,(unsigned char *)buf); + kfree(buf); +} + +struct super_block_operations FAT32_sb_ops = +{ + .write_superblock = fat32_write_superblock, + .put_superblock = fat32_put_superblock, + + .write_inode = fat32_write_inode, +}; + +struct super_block * fat32_read_superblock(struct Disk_Partition_Table_Entry * DPTE,void * buf) +{ + struct super_block * sbp = NULL; + struct FAT32_inode_info * finode = NULL; + struct FAT32_BootSector * fbs = NULL; + struct FAT32_sb_info * fsbi = NULL; + + ////super block + sbp = (struct super_block *)kmalloc(sizeof(struct super_block),0); + memset(sbp,0,sizeof(struct super_block)); + + sbp->sb_ops = &FAT32_sb_ops; + sbp->private_sb_info = (struct FAT32_sb_info *)kmalloc(sizeof(struct FAT32_sb_info),0); + memset(sbp->private_sb_info,0,sizeof(struct FAT32_sb_info)); + + ////fat32 boot sector + fbs = (struct FAT32_BootSector *)buf; + fsbi = sbp->private_sb_info; + fsbi->start_sector = DPTE->start_LBA; + fsbi->sector_count = DPTE->sectors_limit; + fsbi->sector_per_cluster = fbs->BPB_SecPerClus; + fsbi->bytes_per_cluster = fbs->BPB_SecPerClus * fbs->BPB_BytesPerSec; + fsbi->bytes_per_sector = fbs->BPB_BytesPerSec; + fsbi->Data_firstsector = DPTE->start_LBA + fbs->BPB_RsvdSecCnt + fbs->BPB_FATSz32 * fbs->BPB_NumFATs; + fsbi->FAT1_firstsector = DPTE->start_LBA + fbs->BPB_RsvdSecCnt; + fsbi->sector_per_FAT = fbs->BPB_FATSz32; + fsbi->NumFATs = fbs->BPB_NumFATs; + fsbi->fsinfo_sector_infat = fbs->BPB_FSInfo; + fsbi->bootsector_bk_infat = fbs->BPB_BkBootSec; + + color_printk(BLUE,BLACK,"FAT32 Boot Sector\n\tBPB_FSInfo:%#018lx\n\tBPB_BkBootSec:%#018lx\n\tBPB_TotSec32:%#018lx\n",fbs->BPB_FSInfo,fbs->BPB_BkBootSec,fbs->BPB_TotSec32); + + ////fat32 fsinfo sector + fsbi->fat_fsinfo = (struct FAT32_FSInfo *)kmalloc(sizeof(struct FAT32_FSInfo),0); + memset(fsbi->fat_fsinfo,0,512); + IDE_device_operation.transfer(ATA_READ_CMD,DPTE->start_LBA + fbs->BPB_FSInfo,1,(unsigned char *)fsbi->fat_fsinfo); + + color_printk(BLUE,BLACK,"FAT32 FSInfo\n\tFSI_LeadSig:%#018lx\n\tFSI_StrucSig:%#018lx\n\tFSI_Free_Count:%#018lx\n",fsbi->fat_fsinfo->FSI_LeadSig,fsbi->fat_fsinfo->FSI_StrucSig,fsbi->fat_fsinfo->FSI_Free_Count); + + ////directory entry + sbp->root = (struct dir_entry *)kmalloc(sizeof(struct dir_entry),0); + memset(sbp->root,0,sizeof(struct dir_entry)); + + list_init(&sbp->root->child_node); + list_init(&sbp->root->subdirs_list); + sbp->root->parent = sbp->root; + sbp->root->dir_ops = &FAT32_dentry_ops; + sbp->root->name = (char *)kmalloc(2,0); + sbp->root->name[0] = '/'; + sbp->root->name_length = 1; + + ////index node + sbp->root->dir_inode = (struct index_node *)kmalloc(sizeof(struct index_node),0); + memset(sbp->root->dir_inode,0,sizeof(struct index_node)); + sbp->root->dir_inode->inode_ops = &FAT32_inode_ops; + sbp->root->dir_inode->f_ops = &FAT32_file_ops; + sbp->root->dir_inode->file_size = 0; + sbp->root->dir_inode->blocks = (sbp->root->dir_inode->file_size + fsbi->bytes_per_cluster - 1)/fsbi->bytes_per_sector; + sbp->root->dir_inode->attribute = FS_ATTR_DIR; + sbp->root->dir_inode->sb = sbp; + + ////fat32 root inode + sbp->root->dir_inode->private_index_info = (struct FAT32_inode_info *)kmalloc(sizeof(struct FAT32_inode_info),0); + memset(sbp->root->dir_inode->private_index_info,0,sizeof(struct FAT32_inode_info)); + finode = (struct FAT32_inode_info *)sbp->root->dir_inode->private_index_info; + finode->first_cluster = fbs->BPB_RootClus; + finode->dentry_location = 0; + finode->dentry_position = 0; + finode->create_date = 0; + finode->create_time = 0; + finode->write_date = 0; + finode->write_time = 0; + + return sbp; +} + + +struct file_system_type FAT32_fs_type= +{ + .name = "FAT32", + .fs_flags = 0, + .read_superblock = fat32_read_superblock, + .next = NULL, +}; + +void DISK1_FAT32_FS_init() +{ + int i; + unsigned char buf[512]; + struct dir_entry * dentry = NULL; + struct Disk_Partition_Table DPT = {0}; + + register_filesystem(&FAT32_fs_type); + + memset(buf,0,512); + IDE_device_operation.transfer(ATA_READ_CMD,0x0,1,(unsigned char *)buf); + DPT = *(struct Disk_Partition_Table *)buf; + color_printk(BLUE,BLACK,"DPTE[0] start_LBA:%#018lx\ttype:%#018lx\n",DPT.DPTE[0].start_LBA,DPT.DPTE[0].type); + + memset(buf,0,512); + IDE_device_operation.transfer(ATA_READ_CMD,DPT.DPTE[0].start_LBA,1,(unsigned char *)buf); + + root_sb = mount_fs("FAT32",&DPT.DPTE[0],buf); //not dev node +} + + diff --git a/kernel/fat32.h b/kernel/fat32.h new file mode 100644 index 0000000000000000000000000000000000000000..b20c1ac62f1c701ba509bcc61e64157e656c1de3 --- /dev/null +++ b/kernel/fat32.h @@ -0,0 +1,150 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __FAT32_H__ + +#define __FAT32_H__ + +struct FAT32_BootSector +{ + unsigned char BS_jmpBoot[3]; + unsigned char BS_OEMName[8]; + unsigned short BPB_BytesPerSec; + unsigned char BPB_SecPerClus; + unsigned short BPB_RsvdSecCnt; + unsigned char BPB_NumFATs; + unsigned short BPB_RootEntCnt; + unsigned short BPB_TotSec16; + unsigned char BPB_Media; + unsigned short BPB_FATSz16; + unsigned short BPB_SecPerTrk; + unsigned short BPB_NumHeads; + unsigned int BPB_HiddSec; + unsigned int BPB_TotSec32; + + unsigned int BPB_FATSz32; + unsigned short BPB_ExtFlags; + unsigned short BPB_FSVer; + unsigned int BPB_RootClus; + unsigned short BPB_FSInfo; + unsigned short BPB_BkBootSec; + unsigned char BPB_Reserved[12]; + + unsigned char BS_DrvNum; + unsigned char BS_Reserved1; + unsigned char BS_BootSig; + unsigned int BS_VolID; + unsigned char BS_VolLab[11]; + unsigned char BS_FilSysType[8]; + + unsigned char BootCode[420]; + + unsigned short BS_TrailSig; +}__attribute__((packed)); + + +struct FAT32_FSInfo +{ + unsigned int FSI_LeadSig; + unsigned char FSI_Reserved1[480]; + unsigned int FSI_StrucSig; + unsigned int FSI_Free_Count; + unsigned int FSI_Nxt_Free; + unsigned char FSI_Reserved2[12]; + unsigned int FSI_TrailSig; +}__attribute__((packed)); + +#define ATTR_READ_ONLY (1 << 0) +#define ATTR_HIDDEN (1 << 1) +#define ATTR_SYSTEM (1 << 2) +#define ATTR_VOLUME_ID (1 << 3) +#define ATTR_DIRECTORY (1 << 4) +#define ATTR_ARCHIVE (1 << 5) +#define ATTR_LONG_NAME (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID) + +struct FAT32_Directory +{ + unsigned char DIR_Name[11]; + unsigned char DIR_Attr; + unsigned char DIR_NTRes; //EXT|BASE => 8(BASE).3(EXT) + //BASE:LowerCase(8),UpperCase(0) + //EXT:LowerCase(16),UpperCase(0) + unsigned char DIR_CrtTimeTenth; + unsigned short DIR_CrtTime; + unsigned short DIR_CrtDate; + unsigned short DIR_LastAccDate; + unsigned short DIR_FstClusHI; + unsigned short DIR_WrtTime; + unsigned short DIR_WrtDate; + unsigned short DIR_FstClusLO; + unsigned int DIR_FileSize; +}__attribute__((packed)); + +#define LOWERCASE_BASE (8) +#define LOWERCASE_EXT (16) + +struct FAT32_LongDirectory +{ + unsigned char LDIR_Ord; + unsigned short LDIR_Name1[5]; + unsigned char LDIR_Attr; + unsigned char LDIR_Type; + unsigned char LDIR_Chksum; + unsigned short LDIR_Name2[6]; + unsigned short LDIR_FstClusLO; + unsigned short LDIR_Name3[2]; +}__attribute__((packed)); + +void DISK1_FAT32_FS_init(); + +/////////////FAT32 for VFS + +struct FAT32_sb_info +{ + unsigned long start_sector; + unsigned long sector_count; + + long sector_per_cluster; + long bytes_per_cluster; + long bytes_per_sector; + + unsigned long Data_firstsector; + unsigned long FAT1_firstsector; + unsigned long sector_per_FAT; + unsigned long NumFATs; + + unsigned long fsinfo_sector_infat; + unsigned long bootsector_bk_infat; + + struct FAT32_FSInfo * fat_fsinfo; +}; + +struct FAT32_inode_info +{ + unsigned long first_cluster; + unsigned long dentry_location; ////dentry struct in cluster(0 is root,1 is invalid) + unsigned long dentry_position; ////dentry struct offset in cluster + + unsigned short create_date; + unsigned short create_time; + + unsigned short write_date; + unsigned short write_time; +}; + +unsigned int DISK1_FAT32_read_FAT_Entry(struct FAT32_sb_info * fsbi,unsigned int fat_entry); +unsigned long DISK1_FAT32_write_FAT_Entry(struct FAT32_sb_info * fsbi,unsigned int fat_entry,unsigned int value); +unsigned long FAT32_find_available_cluster(struct FAT32_sb_info * fsbi); + +extern struct index_node_operations FAT32_inode_ops; +extern struct file_operations FAT32_file_ops; +extern struct dir_entry_operations FAT32_dentry_ops; +extern struct super_block_operations FAT32_sb_ops; + +#endif diff --git a/kernel/fcntl.h b/kernel/fcntl.h new file mode 100644 index 0000000000000000000000000000000000000000..acd1018dea437cc80046ab608570f4c70cc91519 --- /dev/null +++ b/kernel/fcntl.h @@ -0,0 +1,31 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __FCNTL_H__ + +#define __FCNTL_H__ + +#define O_RDONLY 00000000 /* Open read-only */ +#define O_WRONLY 00000001 /* Open write-only */ +#define O_RDWR 00000002 /* Open read/write */ +#define O_ACCMODE 00000003 /* Mask for file access modes */ + +#define O_CREAT 00000100 /* Create file if it does not exist */ +#define O_EXCL 00000200 /* Fail if file already exists */ +#define O_NOCTTY 00000400 /* Do not assign controlling terminal */ +#define O_TRUNC 00001000 /* If the file exists and is a regular file, and the file is successfully opened O_RDWR or O_WRONLY, its length shall be truncated to 0 */ +#define O_APPEND 00002000 /* the file offset shall be set to the end of the file */ +#define O_NONBLOCK 00004000 /* Non-blocking I/O mode */ + +#define O_EXEC 00010000 /* Open for execute only (non-directory files) */ +#define O_SEARCH 00020000 /* Open directory for search only */ +#define O_DIRECTORY 00040000 /* must be a directory */ +#define O_NOFOLLOW 00100000 /* Do not follow symbolic links */ + +#endif diff --git a/kernel/font.h b/kernel/font.h index 818194401584aa124713ed2cc1cbe06ea7277c1d..69db6c66b0d68bc2c97649c99bdd1c0cee195579 100644 --- a/kernel/font.h +++ b/kernel/font.h @@ -8,6 +8,7 @@ ***************************************************/ #ifndef __FONT_H__ + #define __FONT_H__ unsigned char font_ascii[256][16]= diff --git a/kernel/gate.h b/kernel/gate.h index 886fadbb8d7b02d2d5c49b8b364b3cb8fb0273e2..a8cc4d5a845adaf9e5b63305033d75fd9f66fc52 100644 --- a/kernel/gate.h +++ b/kernel/gate.h @@ -8,6 +8,7 @@ ***************************************************/ #ifndef __GATE_H__ + #define __GATE_H__ struct desc_struct @@ -22,7 +23,6 @@ struct gate_struct extern struct desc_struct GDT_Table[]; extern struct gate_struct IDT_Table[]; -extern unsigned int TSS64_Table[26]; /* @@ -52,6 +52,16 @@ do \ ); \ }while(0) +/* + +*/ + +inline void set_tss_descriptor(unsigned int n,void * addr) +{ + unsigned long limit = 103; + *(unsigned long *)(GDT_Table + n) = (limit & 0xffff) | (((unsigned long)addr & 0xffff) << 16) | (((unsigned long)addr >> 16 & 0xff) << 32) | ((unsigned long)0x89 << 40) | ((limit >> 16 & 0xf) << 48) | (((unsigned long)addr >> 24 & 0xff) << 56); /////89 is attribute + *(unsigned long *)(GDT_Table + n + 1) = ((unsigned long)addr >> 32 & 0xffffffff) | 0; +} /* @@ -106,20 +116,20 @@ inline void set_system_intr_gate(unsigned int n,unsigned char ist,void * addr) / */ -void set_tss64(unsigned long rsp0,unsigned long rsp1,unsigned long rsp2,unsigned long ist1,unsigned long ist2,unsigned long ist3, +void set_tss64(unsigned int * Table,unsigned long rsp0,unsigned long rsp1,unsigned long rsp2,unsigned long ist1,unsigned long ist2,unsigned long ist3, unsigned long ist4,unsigned long ist5,unsigned long ist6,unsigned long ist7) { - *(unsigned long *)(TSS64_Table+1) = rsp0; - *(unsigned long *)(TSS64_Table+3) = rsp1; - *(unsigned long *)(TSS64_Table+5) = rsp2; - - *(unsigned long *)(TSS64_Table+9) = ist1; - *(unsigned long *)(TSS64_Table+11) = ist2; - *(unsigned long *)(TSS64_Table+13) = ist3; - *(unsigned long *)(TSS64_Table+15) = ist4; - *(unsigned long *)(TSS64_Table+17) = ist5; - *(unsigned long *)(TSS64_Table+19) = ist6; - *(unsigned long *)(TSS64_Table+21) = ist7; + *(unsigned long *)(Table+1) = rsp0; + *(unsigned long *)(Table+3) = rsp1; + *(unsigned long *)(Table+5) = rsp2; + + *(unsigned long *)(Table+9) = ist1; + *(unsigned long *)(Table+11) = ist2; + *(unsigned long *)(Table+13) = ist3; + *(unsigned long *)(Table+15) = ist4; + *(unsigned long *)(Table+17) = ist5; + *(unsigned long *)(Table+19) = ist6; + *(unsigned long *)(Table+21) = ist7; } diff --git a/kernel/head.S b/kernel/head.S index 9e9f2b466cef7ec5e26efef0458b20954c851af3..82372beb6c0f3df34a52a39cf6d80851aca8c343 100644 --- a/kernel/head.S +++ b/kernel/head.S @@ -12,17 +12,36 @@ .section .text ENTRY(_start) +#ifndef UEFI + mov $0x10, %ax +#else + movq $0x1b, %rcx //if APU + rdmsr + bt $8, %rax + jnc 1f // APU run 0x10->ax mov %ss, %ax + jmp 2f + +1: + mov $0x10, %ax +2: +#endif mov %ax, %ds mov %ax, %es mov %ax, %fs mov %ax, %ss mov $0x7E00, %esp +#ifdef UEFI + movq $0x1b, %rcx //if APU + rdmsr + bt $8, %rax + jnc 3f // APU do not load cr3 movq $0x101000, %rax movq %rax, %cr3 - +3: +#endif //======= load GDTR lgdt GDT_POINTER(%rip) @@ -62,6 +81,11 @@ entry64: movq %rax, %ss movq _stack_start(%rip), %rsp /* rsp address */ + movq $0x1b, %rcx //if APU + rdmsr + bt $8, %rax + jnc start_smp + setup_IDT: leaq ignore_int(%rip), %rdx movq $(0x08 << 16), %rax @@ -83,7 +107,7 @@ rp_sidt: jne rp_sidt setup_TSS64: - leaq TSS64_Table(%rip), %rdx + leaq init_tss(%rip), %rdx xorq %rax, %rax xorq %rcx, %rcx movq $0x89, %rax @@ -114,6 +138,15 @@ setup_TSS64: go_to_kernel: .quad Start_Kernel +start_smp: + movq go_to_smp_kernel(%rip), %rax /* movq address */ + pushq $0x08 + pushq %rax + lretq + +go_to_smp_kernel: + .quad Start_SMP + //======= ignore_int @@ -186,8 +219,6 @@ int_msg: ENTRY(_stack_start) .quad init_task_union + 32768 - - //======= init page .align 8 @@ -195,36 +226,61 @@ ENTRY(_stack_start) __PML4E: - .quad 0x102007 + .quad 0x102003 .fill 255,8,0 - .quad 0x102007 + .quad 0x102003 .fill 255,8,0 .org 0x2000 __PDPTE: - .quad 0x103007 /* 0x103003 */ + .quad 0x103003 /* 0x103003 */ .fill 511,8,0 .org 0x3000 __PDE: - .quad 0x000087 - .quad 0x200087 - .quad 0x400087 - .quad 0x600087 - .quad 0x800087 - .quad 0xa00087 /*0x a00000*/ - .quad 0xc00087 - .quad 0xe00087 - .quad 0x1000087 - .quad 0x1200087 /*0x1000000*/ - .quad 0x1400087 - .quad 0x1600087 - .quad 0x1800087 - .fill 499,8,0 + .quad 0x000083 + .quad 0x200083 + .quad 0x400083 + .quad 0x600083 + .quad 0x800083 /* 0x800083 */ + .quad 0xa00083 + .quad 0xc00083 + .quad 0xe00083 + .quad 0x1000083 + .quad 0x1200083 + .quad 0x1400083 + .quad 0x1600083 + .quad 0x1800083 + .quad 0x1a00083 + .quad 0x1c00083 + .quad 0x1e00083 + .quad 0x2000083 + .quad 0x2200083 + .quad 0x2400083 + .quad 0x2600083 + .quad 0x2800083 + .quad 0x2a00083 + .quad 0x2c00083 + .quad 0x2e00083 + + +#ifndef UEFI + .quad 0xe0000083 /*0x 3000000*/ + .quad 0xe0200083 + .quad 0xe0400083 + .quad 0xe0600083 + .quad 0xe0800083 + .quad 0xe0a00083 + .quad 0xe0c00083 + .quad 0xe0e00083 + .fill 480,8,0 +#else + .fill 488,8,0 +#endif //======= GDT_Table @@ -242,7 +298,7 @@ GDT_Table: .quad 0x0000f20000000000 /*6 USER Data 64-bit Segment 30*/ .quad 0x00cf9a000000ffff /*7 KERNEL Code 32-bit Segment 38*/ .quad 0x00cf92000000ffff /*8 KERNEL Data 32-bit Segment 40*/ - .fill 10,8,0 /*10 ~ 11 TSS (jmp one segment <9>) in long-mode 128-bit 50*/ + .fill 100,8,0 /*10 ~ 11 TSS (jmp one segment <9>) in long-mode 128-bit 50*/ GDT_END: GDT_POINTER: @@ -260,17 +316,3 @@ IDT_END: IDT_POINTER: IDT_LIMIT: .word IDT_END - IDT_Table - 1 IDT_BASE: .quad IDT_Table - -//======= TSS64_Table - -.globl TSS64_Table - -TSS64_Table: - .fill 13,8,0 -TSS64_END: - - -TSS64_POINTER: -TSS64_LIMIT: .word TSS64_END - TSS64_Table - 1 -TSS64_BASE: .quad TSS64_Table - diff --git a/kernel/interrupt.c b/kernel/interrupt.c index 904f6e7e6560fda8cdad1de4a535458edb00d160..00838b2b140153d2e87391cff353f1f1b5d22f87 100644 --- a/kernel/interrupt.c +++ b/kernel/interrupt.c @@ -10,9 +10,6 @@ #include "interrupt.h" #include "linkage.h" #include "lib.h" -#include "printk.h" -#include "memory.h" -#include "gate.h" #include "ptrace.h" /* @@ -102,6 +99,21 @@ Build_IRQ(0x37) */ +Build_IRQ(0xc8) +Build_IRQ(0xc9) +Build_IRQ(0xca) +Build_IRQ(0xcb) +Build_IRQ(0xcc) +Build_IRQ(0xcd) +Build_IRQ(0xce) +Build_IRQ(0xcf) +Build_IRQ(0xd0) +Build_IRQ(0xd1) + +/* + +*/ + void (* interrupt[24])(void)= { IRQ0x20_interrupt, @@ -130,47 +142,105 @@ void (* interrupt[24])(void)= IRQ0x37_interrupt, }; -void init_interrupt() +/* + +*/ + +void (* SMP_interrupt[10])(void)= { - int i; - for(i = 32;i < 56;i++) - { - set_intr_gate(i , 2 , interrupt[i - 32]); - } - - color_printk(RED,BLACK,"8259A init \n"); - - //8259A-master ICW1-4 - io_out8(0x20,0x11); - io_out8(0x21,0x20); - io_out8(0x21,0x04); - io_out8(0x21,0x01); - - //8259A-slave ICW1-4 - io_out8(0xa0,0x11); - io_out8(0xa1,0x28); - io_out8(0xa1,0x02); - io_out8(0xa1,0x01); - - //8259A-M/S OCW1 - io_out8(0x21,0xfd); - io_out8(0xa1,0xff); - - sti(); + IRQ0xc8_interrupt, + IRQ0xc9_interrupt, + IRQ0xca_interrupt, + IRQ0xcb_interrupt, + IRQ0xcc_interrupt, + IRQ0xcd_interrupt, + IRQ0xce_interrupt, + IRQ0xcf_interrupt, + IRQ0xd0_interrupt, + IRQ0xd1_interrupt, +}; + +/* + +*/ + +int register_irq(unsigned long irq, + void * arg, + void (*handler)(unsigned long nr, unsigned long parameter, struct pt_regs * regs), + unsigned long parameter, + hw_int_controller * controller, + char * irq_name) +{ + irq_desc_T * p = &interrupt_desc[irq - 32]; + + p->controller = controller; + p->irq_name = irq_name; + p->parameter = parameter; + p->flags = 0; + p->handler = handler; + + p->controller->install(irq,arg); + p->controller->enable(irq); + + return 1; } /* */ -void do_IRQ(struct pt_regs * regs,unsigned long nr) //regs,nr +int unregister_irq(unsigned long irq) { - unsigned char x; - color_printk(RED,BLACK,"do_IRQ:%#018lx\t",nr); - x = io_in8(0x60); - color_printk(RED,BLACK,"key code:%#018lx\t",x); - io_out8(0x20,0x20); - color_printk(RED,BLACK,"regs:%#018lx\t\n",regs,regs->rip,regs->rsp); + irq_desc_T * p = &interrupt_desc[irq - 32]; + + p->controller->disable(irq); + p->controller->uninstall(irq); + + p->controller = NULL; + p->irq_name = NULL; + p->parameter = NULL; + p->flags = 0; + p->handler = NULL; + + return 1; +} + + +/* + +*/ + +int register_IPI(unsigned long irq, + void * arg, + void (*handler)(unsigned long nr, unsigned long parameter, struct pt_regs * regs), + unsigned long parameter, + hw_int_controller * controller, + char * irq_name) +{ + irq_desc_T * p = &SMP_IPI_desc[irq - 200]; + + p->controller = NULL; + p->irq_name = irq_name; + p->parameter = parameter; + p->flags = 0; + p->handler = handler; + + return 1; } +/* + +*/ + +int unregister_IPI(unsigned long irq) +{ + irq_desc_T * p = &SMP_IPI_desc[irq - 200]; + + p->controller = NULL; + p->irq_name = NULL; + p->parameter = NULL; + p->flags = 0; + p->handler = NULL; + return 1; +} diff --git a/kernel/interrupt.h b/kernel/interrupt.h index 06ac07f83329f5c18d40d3ed0af6c8976f2f3c95..183f0346ef9125b293be6452473845e2c354b839 100644 --- a/kernel/interrupt.h +++ b/kernel/interrupt.h @@ -7,7 +7,9 @@ * ***************************************************/ #ifndef __INTERRUPT_H__ + #define __INTERRUPT_H__ + #include "linkage.h" #include "ptrace.h" @@ -15,12 +17,76 @@ */ -void init_interrupt(); +typedef struct hw_int_type +{ + void (*enable)(unsigned long irq); + void (*disable)(unsigned long irq); + + unsigned long (*install)(unsigned long irq,void * arg); + void (*uninstall)(unsigned long irq); + + void (*ack)(unsigned long irq); +}hw_int_controller; /* */ -void do_IRQ(struct pt_regs * regs,unsigned long nr); +typedef struct { + hw_int_controller * controller; + + char * irq_name; + unsigned long parameter; + void (*handler)(unsigned long nr, unsigned long parameter, struct pt_regs * regs); + unsigned long flags; +}irq_desc_T; + +/* + +*/ + +#define NR_IRQS 24 + +irq_desc_T interrupt_desc[NR_IRQS] = {0}; +irq_desc_T SMP_IPI_desc[10] = {0}; + +/* + +*/ + +int register_irq(unsigned long irq, + void * arg, + void (*handler)(unsigned long nr, unsigned long parameter, struct pt_regs * regs), + unsigned long parameter, + hw_int_controller * controller, + char * irq_name); + +/* + +*/ + +int unregister_irq(unsigned long irq); + +/* + +*/ + +int register_IPI(unsigned long irq, + void * arg, + void (*handler)(unsigned long nr, unsigned long parameter, struct pt_regs * regs), + unsigned long parameter, + hw_int_controller * controller, + char * irq_name); + +/* + +*/ + +int unregister_IPI(unsigned long irq); + +extern void (* interrupt[24])(void); +extern void (* SMP_interrupt[10])(void); + +extern void do_IRQ(struct pt_regs * regs,unsigned long nr); #endif diff --git a/kernel/io.h b/kernel/io.h new file mode 100644 index 0000000000000000000000000000000000000000..d5a6b9f82ec6be7a9903bacf72e6ee036f32d7e0 --- /dev/null +++ b/kernel/io.h @@ -0,0 +1,63 @@ +#ifndef _ASM_IO_H +#define _ASM_IO_H + +/* + * This file contains the definitions for the x86 IO instructions + * inb/inw/inl/outb/outw/outl and the "string versions" of the same + * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing" + * versions of the single-IO instructions (inb_p/inw_p/..). + * + * This file is not meant to be obfuscating: it's just complicated + * to (a) handle it all in a way that makes gcc able to optimize it + * as well as possible and (b) trying to avoid writing the same thing + * over and over again with slight variations and possibly making a + * mistake somewhere. + */ + +/* + * Thanks to James van Artsdalen for a better timing-fix than + * the two short jumps: using outb's to a nonexistent port seems + * to guarantee better timings even on fast machines. + * + * On the other hand, I'd like to be sure of a non-existent port: + * I feel a bit unsafe about using 0x80 (should be safe, though) + * + * Linus + */ +#include "lib.h" + +#ifdef SLOW_IO_BY_JUMPING +#define __SLOW_DOWN_IO __asm__ __volatile__("jmp 1f\n1:\tjmp 1f\n1:") +#else +#define __SLOW_DOWN_IO __asm__ __volatile__("outb %al,$0x80") +#endif + +#ifdef REALLY_SLOW_IO +#define SLOW_DOWN_IO { __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; __SLOW_DOWN_IO; } +#else +#define SLOW_DOWN_IO __SLOW_DOWN_IO +#endif + +static inline unsigned int inb(unsigned short port) +{ + unsigned int ret = io_in8(port); +} + +static inline unsigned int inb_p(unsigned short port) +{ + unsigned int ret = io_in8(port); + __SLOW_DOWN_IO; +} + +static inline void outb(int val, unsigned short port) +{ + io_out8(port, val); +} + +static inline void outb_p(int val, unsigned short port) +{ + io_out8(port, val); + SLOW_DOWN_IO; +} + +#endif \ No newline at end of file diff --git a/kernel/keyboard.c b/kernel/keyboard.c new file mode 100644 index 0000000000000000000000000000000000000000..bfcb148d19724b89e6a74a7b13130b27a30a8c5e --- /dev/null +++ b/kernel/keyboard.c @@ -0,0 +1,197 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "keyboard.h" +#include "lib.h" +#include "APIC.h" +#include "memory.h" +#include "printk.h" +#include "VFS.h" +#include "waitqueue.h" + +/* + +*/ + +struct keyboard_inputbuffer * p_kb = NULL; + +wait_queue_T keyboard_wait_queue; + +void keyboard_handler(unsigned long nr, unsigned long parameter, struct pt_regs * regs) +{ + unsigned char x; + x = io_in8(0x60); + color_printk(WHITE,BLACK,"(K:%02x)",x); + + if(p_kb->p_head == p_kb->buf + KB_BUF_SIZE) + p_kb->p_head = p_kb->buf; + + *p_kb->p_head = x; + p_kb->count++; + p_kb->p_head ++; + + wakeup(&keyboard_wait_queue,TASK_UNINTERRUPTIBLE); +} + + +hw_int_controller keyboard_int_controller = +{ + .enable = IOAPIC_enable, + .disable = IOAPIC_disable, + .install = IOAPIC_install, + .uninstall = IOAPIC_uninstall, + .ack = IOAPIC_edge_ack, +}; + +/* + +*/ + +long keyboard_open(struct index_node * inode,struct file * filp) +{ + filp->private_data = p_kb; + + p_kb->p_head = p_kb->buf; + p_kb->p_tail = p_kb->buf; + p_kb->count = 0; + memset(p_kb->buf,0,KB_BUF_SIZE); + + return 1; +} + +long keyboard_close(struct index_node * inode,struct file * filp) +{ + filp->private_data = NULL; + + p_kb->p_head = p_kb->buf; + p_kb->p_tail = p_kb->buf; + p_kb->count = 0; + memset(p_kb->buf,0,KB_BUF_SIZE); + + return 1; +} + +#define KEY_CMD_RESET_BUFFER 0 + +long keyboard_ioctl(struct index_node * inode,struct file * filp,unsigned long cmd,unsigned long arg) +{ + switch(cmd) + { + + case KEY_CMD_RESET_BUFFER: + p_kb->p_head = p_kb->buf; + p_kb->p_tail = p_kb->buf; + p_kb->count = 0; + memset(p_kb->buf,0,KB_BUF_SIZE); + break; + + default: + break; + } + + return 0; +} + +long keyboard_read(struct file * filp,char * buf,unsigned long count,long * position) +{ + long counter = 0; + unsigned char * tail = NULL; + + + if(p_kb->count == 0) + sleep_on(&keyboard_wait_queue); + + counter = p_kb->count >= count? count:p_kb->count; + tail = p_kb->p_tail; + + if(counter <= (p_kb->buf + KB_BUF_SIZE - tail)) + { + copy_to_user(tail,buf,counter); + p_kb->p_tail += counter; + } + else + { + copy_to_user(tail,buf,(p_kb->buf + KB_BUF_SIZE - tail)); + copy_to_user(p_kb->p_head,buf,counter - (p_kb->buf + KB_BUF_SIZE - tail)); + p_kb->p_tail = p_kb->p_head + (counter - (p_kb->buf + KB_BUF_SIZE - tail)); + } + p_kb->count -= counter; + + return counter; +} + +long keyboard_write(struct file * filp,char * buf,unsigned long count,long * position) +{ + return 0; +} + + +struct file_operations keyboard_fops = +{ + .open = keyboard_open, + .close = keyboard_close, + .ioctl = keyboard_ioctl, + .read = keyboard_read, + .write = keyboard_write, +}; + +/* + +*/ + + +void keyboard_init() +{ + struct IO_APIC_RET_entry entry; + unsigned long i,j; + + wait_queue_init(&keyboard_wait_queue,NULL); + + p_kb = (struct keyboard_inputbuffer *)kmalloc(sizeof(struct keyboard_inputbuffer),0); + + p_kb->p_head = p_kb->buf; + p_kb->p_tail = p_kb->buf; + p_kb->count = 0; + memset(p_kb->buf,0,KB_BUF_SIZE); + + entry.vector = 0x21; + entry.deliver_mode = APIC_ICR_IOAPIC_Fixed ; + entry.dest_mode = ICR_IOAPIC_DELV_PHYSICAL; + entry.deliver_status = APIC_ICR_IOAPIC_Idle; + entry.polarity = APIC_IOAPIC_POLARITY_HIGH; + entry.irr = APIC_IOAPIC_IRR_RESET; + entry.trigger = APIC_ICR_IOAPIC_Edge; + entry.mask = APIC_ICR_IOAPIC_Masked; + entry.reserved = 0; + + entry.destination.physical.reserved1 = 0; + entry.destination.physical.phy_dest = 0; + entry.destination.physical.reserved2 = 0; + + wait_KB_write(); + io_out8(PORT_KB_CMD,KBCMD_WRITE_CMD); + wait_KB_write(); + io_out8(PORT_KB_DATA,KB_INIT_MODE); + + for(i = 0;i<1000;i++) + for(j = 0;j<1000;j++) + nop(); + + register_irq(0x21, &entry , &keyboard_handler, (unsigned long)p_kb, &keyboard_int_controller, "ps/2 keyboard"); +} + +/* + +*/ + +void keyboard_exit() +{ + unregister_irq(0x21); + kfree((unsigned long *)p_kb); +} diff --git a/kernel/keyboard.h b/kernel/keyboard.h new file mode 100644 index 0000000000000000000000000000000000000000..6da9ecf64b8d449604bbb101274184aca2814bdf --- /dev/null +++ b/kernel/keyboard.h @@ -0,0 +1,63 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __KEYBOARD_H__ + +#define __KEYBOARD_H__ + +#define KB_BUF_SIZE 100 + +struct keyboard_inputbuffer +{ + unsigned char * p_head; + unsigned char * p_tail; + int count; + unsigned char buf[KB_BUF_SIZE]; +}; + +extern struct file_operations keyboard_fops; + +/* + +*/ + + +#define PORT_KB_DATA 0x60 +#define PORT_KB_STATUS 0x64 +#define PORT_KB_CMD 0x64 + +#define KBSTATUS_IBF 0x02 +#define KBSTATUS_OBF 0x01 + +#define KBCMD_WRITE_CMD 0x60 +#define KBCMD_READ_CMD 0x20 + +#define KB_INIT_MODE 0x47 + +/* + +*/ + +#define wait_KB_write() while(io_in8(PORT_KB_STATUS) & KBSTATUS_IBF) +#define wait_KB_read() while(io_in8(PORT_KB_STATUS) & KBSTATUS_OBF) + +/* + +*/ + +void keyboard_init(); +void keyboard_exit(); + +/* + +*/ + +void analysis_keycode(); + +#endif diff --git a/kernel/lib.h b/kernel/lib.h index 556bcbdaf79aaf8ad27f1f40cad317bf7d263a4e..53857dcbb835f7cc6121d083d0ba48fd214c49d4 100644 --- a/kernel/lib.h +++ b/kernel/lib.h @@ -8,8 +8,8 @@ ***************************************************/ #ifndef __LIB_H__ -#define __LIB_H__ +#define __LIB_H__ #define NULL 0 @@ -25,6 +25,8 @@ #define nop() __asm__ __volatile__ ("nop \n\t") #define io_mfence() __asm__ __volatile__ ("mfence \n\t":::"memory") +#define hlt() __asm__ __volatile__ ("hlt \n\t") +#define pause() __asm__ __volatile__ ("pause \n\t") struct List { @@ -178,8 +180,7 @@ inline char * strcpy(char * Dest,char * Src) "jne 1b \n\t" : :"S"(Src),"D"(Dest) - : - + :"ax","memory" ); return Dest; } @@ -203,7 +204,7 @@ inline char * strncpy(char * Dest,char * Src,long Count) "2: \n\t" : :"S"(Src),"D"(Dest),"c"(Count) - : + :"ax","memory" ); return Dest; } @@ -225,7 +226,7 @@ inline char * strcat(char * Dest,char * Src) "jne 1b \n\t" : :"S"(Src),"D"(Dest),"a"(0),"c"(0xffffffff) - : + :"memory" ); return Dest; } @@ -348,11 +349,12 @@ inline unsigned long bit_clean(unsigned long * addr,unsigned long nr) inline unsigned char io_in8(unsigned short port) { unsigned char ret = 0; - __asm__ __volatile__( "inb %%dx, %0 \n\t" - "mfence \n\t" - :"=a"(ret) - :"d"(port) - :"memory"); + __asm__ __volatile__ ( "inb %%dx, %0 \n\t" + "mfence \n\t" + :"=a"(ret) + :"d"(port) + :"memory" + ); return ret; } @@ -363,11 +365,12 @@ inline unsigned char io_in8(unsigned short port) inline unsigned int io_in32(unsigned short port) { unsigned int ret = 0; - __asm__ __volatile__( "inl %%dx, %0 \n\t" - "mfence \n\t" - :"=a"(ret) - :"d"(port) - :"memory"); + __asm__ __volatile__ ( "inl %%dx, %0 \n\t" + "mfence \n\t" + :"=a"(ret) + :"d"(port) + :"memory" + ); return ret; } @@ -377,11 +380,12 @@ inline unsigned int io_in32(unsigned short port) inline void io_out8(unsigned short port,unsigned char value) { - __asm__ __volatile__( "outb %0, %%dx \n\t" - "mfence \n\t" - : - :"a"(value),"d"(port) - :"memory"); + __asm__ __volatile__ ( "outb %0, %%dx \n\t" + "mfence \n\t" + : + :"a"(value),"d"(port) + :"memory" + ); } /* @@ -390,11 +394,12 @@ inline void io_out8(unsigned short port,unsigned char value) inline void io_out32(unsigned short port,unsigned int value) { - __asm__ __volatile__( "outl %0, %%dx \n\t" - "mfence \n\t" - : - :"a"(value),"d"(port) - :"memory"); + __asm__ __volatile__ ( "outl %0, %%dx \n\t" + "mfence \n\t" + : + :"a"(value),"d"(port) + :"memory" + ); } /* @@ -411,15 +416,93 @@ inline unsigned long rdmsr(unsigned long address) { unsigned int tmp0 = 0; unsigned int tmp1 = 0; - __asm__ __volatile__("rdmsr \n\t":"=d"(tmp0),"=a"(tmp1):"c"(address):"memory"); + __asm__ __volatile__ ("rdmsr \n\t":"=d"(tmp0),"=a"(tmp1):"c"(address):"memory"); return (unsigned long)tmp0<<32 | tmp1; } inline void wrmsr(unsigned long address,unsigned long value) { - __asm__ __volatile__("wrmsr \n\t"::"d"(value >> 32),"a"(value & 0xffffffff),"c"(address):"memory"); + __asm__ __volatile__ ("wrmsr \n\t"::"d"(value >> 32),"a"(value & 0xffffffff),"c"(address):"memory"); +} + +inline unsigned long get_rsp() +{ + unsigned long tmp = 0; + __asm__ __volatile__ ( "movq %%rsp, %0 \n\t":"=r"(tmp)::"memory"); + return tmp; +} + +inline unsigned long get_rflags() +{ + unsigned long tmp = 0; + __asm__ __volatile__ ( "pushfq \n\t" + "movq (%%rsp), %0 \n\t" + "popfq \n\t" + :"=r"(tmp) + : + :"memory" + ); + return tmp; +} + +inline long verify_area(unsigned char* addr,unsigned long size) +{ + if(((unsigned long)addr + size) <= (unsigned long)0x00007fffffffffff ) + return 1; + else + return 0; } +inline long copy_from_user(void * from,void * to,unsigned long size) +{ + unsigned long d0,d1; + if(!verify_area(from,size)) + return 0; + __asm__ __volatile__ ( "rep \n\t" + "movsq \n\t" + "movq %3, %0 \n\t" + "rep \n\t" + "movsb \n\t" + :"=&c"(size),"=&D"(d0),"=&S"(d1) + :"r"(size & 7),"0"(size / 8),"1"(to),"2"(from) + :"memory" + ); + return size; +} +inline long copy_to_user(void * from,void * to,unsigned long size) +{ + unsigned long d0,d1; + if(!verify_area(to,size)) + return 0; + __asm__ __volatile__ ( "rep \n\t" + "movsq \n\t" + "movq %3, %0 \n\t" + "rep \n\t" + "movsb \n\t" + :"=&c"(size),"=&D"(d0),"=&S"(d1) + :"r"(size & 7),"0"(size / 8),"1"(to),"2"(from) + :"memory" + ); + return size; +} + +inline long strncpy_from_user(void * from,void * to,unsigned long size) +{ + if(!verify_area(from,size)) + return 0; + + strncpy(to,from,size); + return size; +} + +inline long strnlen_user(void * src,unsigned long maxlen) +{ + unsigned long size = strlen(src); + if(!verify_area(src,size)) + return 0; + + return size <= maxlen ? size : maxlen; +} #endif diff --git a/kernel/linkage.h b/kernel/linkage.h index f30bd3bb7ff45ff160c5e1918f7ff25747fde9e8..12c53f3d242705443c58d42c74e74d606ecaa825 100644 --- a/kernel/linkage.h +++ b/kernel/linkage.h @@ -8,6 +8,7 @@ ***************************************************/ #ifndef _LINKAGE_H_ + #define _LINKAGE_H_ /* diff --git a/kernel/main.c b/kernel/main.c index cd21594955308d21871904c1673b406e05c7dda5..802cde026763e89c56e27eb2ea2ce5f72b5c8a97 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -7,88 +7,229 @@ * ***************************************************/ -#include "UEFI_boot_param_info.h" #include "lib.h" #include "printk.h" #include "gate.h" #include "trap.h" #include "memory.h" #include "task.h" -#include "interrupt.h" +#include "cpu.h" + +#if APIC +#include "APIC.h" +#else +#include "8259A.h" +#endif + +#include "keyboard.h" +#include "mouse.h" +#include "disk.h" +#include "SMP.h" +#include "spinlock.h" +#include "HPET.h" +#include "timer.h" + +#include "atomic.h" +#include "semaphore.h" +#include "fat32.h" /* static var */ +#ifdef UEFI +#include "UEFI_boot_param_info.h" struct KERNEL_BOOT_PARAMETER_INFORMATION *boot_para_info = (struct KERNEL_BOOT_PARAMETER_INFORMATION *)0xffff800000060000; +#endif void Start_Kernel(void) { - int *addr = (int *)0xffff800003000000; - int i; - memset((void *)&_bss, 0, (unsigned long)&_ebss - (unsigned long)&_bss); - + struct INT_CMD_REG icr_entry; + unsigned char * ptr = NULL; + +#ifndef UEFI + Pos.XResolution = 1024; + Pos.YResolution = 768; +#else Pos.XResolution = boot_para_info->Graphics_Info.HorizontalResolution; Pos.YResolution = boot_para_info->Graphics_Info.VerticalResolution; +#endif + + Pos.XPosition = 0; + Pos.YPosition = 0; + + Pos.XCharSize = 8; + Pos.YCharSize = 16; Pos.FB_addr = (int *)0xffff800003000000; Pos.FB_length = (Pos.XResolution * Pos.YResolution * 4 + PAGE_4K_SIZE - 1) & PAGE_4K_MASK; - for(i = 0 ;i<2048*20;i++) - { - *((char *)addr+0)=(char)0x00; - *((char *)addr+1)=(char)0x00; - *((char *)addr+2)=(char)0xff; - *((char *)addr+3)=(char)0x00; - addr +=1; - } - for(i = 0 ;i<2048*20;i++) - { - *((char *)addr+0)=(char)0x00; - *((char *)addr+1)=(char)0xff; - *((char *)addr+2)=(char)0x00; - *((char *)addr+3)=(char)0x00; - addr +=1; - } - for(i = 0 ;i<2048*20;i++) - { - *((char *)addr+0)=(char)0xff; - *((char *)addr+1)=(char)0x00; - *((char *)addr+2)=(char)0x00; - *((char *)addr+3)=(char)0x00; - addr +=1; - } - for(i = 0 ;i<2048*20;i++) - { - *((char *)addr+0)=(char)0xff; - *((char *)addr+1)=(char)0xff; - *((char *)addr+2)=(char)0xff; - *((char *)addr+3)=(char)0x00; - addr +=1; - } + global_pid = 1; + + spin_init(&Pos.printk_lock); load_TR(10); - set_tss64(_stack_start, _stack_start, _stack_start, 0xffff800000007c00, 0xffff800000007c00, 0xffff800000007c00, 0xffff800000007c00, 0xffff800000007c00, 0xffff800000007c00, 0xffff800000007c00); + set_tss64((unsigned int *)&init_tss[0],_stack_start, _stack_start, _stack_start, 0xffff800000007c00, 0xffff800000007c00, 0xffff800000007c00, 0xffff800000007c00, 0xffff800000007c00, 0xffff800000007c00, 0xffff800000007c00); sys_vector_init(); + init_cpu(); + memory_management_struct.start_code = (unsigned long)& _text; memory_management_struct.end_code = (unsigned long)& _etext; memory_management_struct.end_data = (unsigned long)& _edata; - memory_management_struct.end_brk = (unsigned long)& _end; + memory_management_struct.end_rodata = (unsigned long)& _erodata; + memory_management_struct.start_brk = (unsigned long)& _end; - color_printk(RED,BLACK,"boot_para_info->Graphics_Info.HorizontalResolution:%#018lx\tboot_para_info->Graphics_Info.VerticalResolution:%#018lx\tboot_para_info->Graphics_Info.PixelsPerScanLine:%#018lx\n",boot_para_info->Graphics_Info.HorizontalResolution,boot_para_info->Graphics_Info.VerticalResolution,boot_para_info->Graphics_Info.PixelsPerScanLine); +#ifdef UEFI +color_printk(RED,BLACK,"boot_para_info->Graphics_Info.HorizontalResolution:%#018lx\tboot_para_info->Graphics_Info.VerticalResolution:%#018lx\tboot_para_info->Graphics_Info.PixelsPerScanLine:%#018lx\n",boot_para_info->Graphics_Info.HorizontalResolution,boot_para_info->Graphics_Info.VerticalResolution,boot_para_info->Graphics_Info.PixelsPerScanLine); color_printk(RED,BLACK,"boot_para_info->Graphics_Info.FrameBufferBase:%#018lx\tboot_para_info->Graphics_Info.FrameBufferSize:%#018lx\n",boot_para_info->Graphics_Info.FrameBufferBase,boot_para_info->Graphics_Info.FrameBufferSize); +#endif color_printk(RED,BLACK,"memory init \n"); init_memory(); + color_printk(RED,BLACK,"slab init \n"); + slab_init(); + + ptr = (unsigned char *)kmalloc(STACK_SIZE,0) + STACK_SIZE; + ((struct task_struct *)(ptr - STACK_SIZE))->cpu_id = 0; + + init_tss[0].ist1 = (unsigned long)ptr; + init_tss[0].ist2 = (unsigned long)ptr; + init_tss[0].ist3 = (unsigned long)ptr; + init_tss[0].ist4 = (unsigned long)ptr; + init_tss[0].ist5 = (unsigned long)ptr; + init_tss[0].ist6 = (unsigned long)ptr; + init_tss[0].ist7 = (unsigned long)ptr; + + color_printk(RED,BLACK,"frame buffer init \n"); + frame_buffer_init(); + color_printk(WHITE,BLACK,"frame_buffer_init() is OK \n"); + + color_printk(RED,BLACK,"pagetable init \n"); + pagetable_init(); + color_printk(RED,BLACK,"interrupt init \n"); - init_interrupt(); - color_printk(RED,BLACK,"task_init \n"); - task_init(); + #if APIC + APIC_IOAPIC_init(); + #else + init_8259A(); + #endif + + color_printk(RED,BLACK,"schedule init \n"); + schedule_init(); + + color_printk(RED,BLACK,"Soft IRQ init \n"); + softirq_init(); + + color_printk(RED,BLACK,"keyboard init \n"); + keyboard_init(); + + color_printk(RED,BLACK,"mouse init \n"); + mouse_init(); + +// color_printk(RED,BLACK,"disk init \n"); +// disk_init(); + + color_printk(RED,BLACK,"ICR init \n"); + + /* IPI can not work, need to figure out */ +#if 1 + SMP_init(); + + //prepare send INIT IPI + + icr_entry.vector = 0x00; + icr_entry.deliver_mode = APIC_ICR_IOAPIC_INIT; + icr_entry.dest_mode = ICR_IOAPIC_DELV_PHYSICAL; + icr_entry.deliver_status = APIC_ICR_IOAPIC_Idle; + icr_entry.res_1 = 0; + icr_entry.level = ICR_LEVEL_DE_ASSERT; + icr_entry.trigger = APIC_ICR_IOAPIC_Edge; + icr_entry.res_2 = 0; + icr_entry.dest_shorthand = ICR_ALL_EXCLUDE_Self; + icr_entry.res_3 = 0; + icr_entry.destination.x2apic_destination = 0x00; + + wrmsr(0x830,*(unsigned long *)&icr_entry); //INIT IPI + + //prepare send Start-up IPI + + for(global_i = 1;global_i < 4;global_i++) + { + spin_lock(&SMP_lock); + ptr = (unsigned char *)kmalloc(STACK_SIZE,0); + _stack_start = (unsigned long)ptr + STACK_SIZE; + ((struct task_struct *)ptr)->cpu_id = global_i; + + memset(&init_tss[global_i],0,sizeof(struct tss_struct)); + + init_tss[global_i].rsp0 = _stack_start; + init_tss[global_i].rsp1 = _stack_start; + init_tss[global_i].rsp2 = _stack_start; + + ptr = (unsigned char *)kmalloc(STACK_SIZE,0) + STACK_SIZE; + ((struct task_struct *)(ptr - STACK_SIZE))->cpu_id = global_i; + + init_tss[global_i].ist1 = (unsigned long)ptr; + init_tss[global_i].ist2 = (unsigned long)ptr; + init_tss[global_i].ist3 = (unsigned long)ptr; + init_tss[global_i].ist4 = (unsigned long)ptr; + init_tss[global_i].ist5 = (unsigned long)ptr; + init_tss[global_i].ist6 = (unsigned long)ptr; + init_tss[global_i].ist7 = (unsigned long)ptr; + + set_tss_descriptor(10 + global_i * 2,&init_tss[global_i]); + + icr_entry.vector = 0x20; + icr_entry.deliver_mode = ICR_Start_up; + icr_entry.dest_shorthand = ICR_No_Shorthand; + icr_entry.destination.x2apic_destination = global_i; + + wrmsr(0x830,*(unsigned long *)&icr_entry); //Start-up IPI + wrmsr(0x830,*(unsigned long *)&icr_entry); //Start-up IPI + } - while(1); + icr_entry.vector = 0xc8; + icr_entry.destination.x2apic_destination = 1; + icr_entry.deliver_mode = APIC_ICR_IOAPIC_Fixed; + wrmsr(0x830,*(unsigned long *)&icr_entry); + + icr_entry.vector = 0xc9; + wrmsr(0x830,*(unsigned long *)&icr_entry); +#endif + + color_printk(RED,BLACK,"Timer init \n"); + timer_init(); + + /* in HPET_init(), get CRBA will not work on VMware */ + // color_printk(RED,BLACK,"HPET init \n"); + // HPET_init(); +#if 0 + #include "serial.h" + extern struct serial_des rs_table[]; + struct serial_des *info = &rs_table[0]; + init_serial(info, 0); + + color_printk(GREEN, BLACK, "Begin to receive chars from serial!\n"); + //receive_chars(info); +#endif +loop: + while(1) + asm volatile("pause \n\t");/* + color_printk(RED,BLACK,"task init \n"); + task_init(); + sti(); + + while(1) + { +// if(p_kb->count) +// analysis_keycode(); + if(p_mouse->count) + analysis_mousecode(); + //hlt(); + }*/ } diff --git a/kernel/memory.c b/kernel/memory.c index 9203c2c31930a74c29a3d54a08562034f00e6734..36d228bb378e49665bc0d1acc51e9f3e1861706f 100644 --- a/kernel/memory.c +++ b/kernel/memory.c @@ -7,96 +7,118 @@ * ***************************************************/ -#include "UEFI_boot_param_info.h" #include "memory.h" #include "printk.h" #include "lib.h" +#include "errno.h" +#ifdef UEFI +#include "UEFI_boot_param_info.h" +#endif -//// each zone index -int ZONE_DMA_INDEX = 0; -int ZONE_NORMAL_INDEX = 0; //low 1GB RAM ,was mapped in pagetable -int ZONE_UNMAPED_INDEX = 0; //above 1GB RAM,unmapped in pagetable +struct Global_Memory_Descriptor memory_management_struct = {{0},0}; -unsigned long * Global_CR3 = NULL; +struct Slab_cache kmalloc_cache_size[16] = +{ + {32 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {64 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {128 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {256 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {512 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {1024 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, //1KB + {2048 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {4096 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, //4KB + {8192 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {16384 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {32768 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {65536 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, //64KB + {131072 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, //128KB + {262144 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {524288 ,0 ,0 ,NULL ,NULL ,NULL ,NULL}, + {1048576,0 ,0 ,NULL ,NULL ,NULL ,NULL}, //1MB +}; -struct Global_Memory_Descriptor memory_management_struct = {{0},0}; unsigned long page_init(struct Page * page,unsigned long flags) { - if(!page->attribute) + page->attribute |= flags; + + if(!page->reference_count || (page->attribute & PG_Shared)) { - *(memory_management_struct.bits_map + ((page->PHY_address >> PAGE_2M_SHIFT) >> 6)) |= 1UL << (page->PHY_address >> PAGE_2M_SHIFT) % 64; - page->attribute = flags; page->reference_count++; - page->zone_struct->page_using_count++; - page->zone_struct->page_free_count--; - page->zone_struct->total_pages_link++; - } - else if((page->attribute & PG_Referenced) || (page->attribute & PG_K_Share_To_U) || (flags & PG_Referenced) || (flags & PG_K_Share_To_U)) + page->zone_struct->total_pages_link++; + } + + return 1; +} + + +unsigned long page_clean(struct Page * page) +{ + page->reference_count--; + page->zone_struct->total_pages_link--; + + if(!page->reference_count) { - page->attribute |= flags; - page->reference_count++; - page->zone_struct->total_pages_link++; + page->attribute &= PG_PTable_Maped; } - else + + return 1; +} + +unsigned long get_page_attribute(struct Page * page) +{ + if(page == NULL) { - *(memory_management_struct.bits_map + ((page->PHY_address >> PAGE_2M_SHIFT) >> 6)) |= 1UL << (page->PHY_address >> PAGE_2M_SHIFT) % 64; - page->attribute |= flags; + color_printk(RED,BLACK,"get_page_attribute() ERROR: page == NULL\n"); + return 0; } - return 0; + else + return page->attribute; } - -unsigned long page_clean(struct Page * page) +unsigned long set_page_attribute(struct Page * page,unsigned long flags) { - if(!page->attribute) + if(page == NULL) { - page->attribute = 0; - } - else if((page->attribute & PG_Referenced) || (page->attribute & PG_K_Share_To_U)) - { - page->reference_count--; - page->zone_struct->total_pages_link--; - if(!page->reference_count) - { - page->attribute = 0; - page->zone_struct->page_using_count--; - page->zone_struct->page_free_count++; - } + color_printk(RED,BLACK,"set_page_attribute() ERROR: page == NULL\n"); + return 0; } else { - *(memory_management_struct.bits_map + ((page->PHY_address >> PAGE_2M_SHIFT) >> 6)) &= ~(1UL << (page->PHY_address >> PAGE_2M_SHIFT) % 64); - - page->attribute = 0; - page->reference_count = 0; - page->zone_struct->page_using_count--; - page->zone_struct->page_free_count++; - page->zone_struct->total_pages_link--; + page->attribute = flags; + return 1; } - return 0; } - void init_memory() { int i,j; unsigned long TotalMem = 0 ; - struct EFI_E820_MEMORY_DESCRIPTOR *p = NULL; + unsigned long * tmp = NULL; color_printk(BLUE,BLACK,"Display Physics Address MAP,Type(1:RAM,2:ROM or Reserved,3:ACPI Reclaim Memory,4:ACPI NVS Memory,Others:Undefine)\n"); - p = (struct EFI_E820_MEMORY_DESCRIPTOR *)boot_para_info->E820_Info.E820_Entry; - +#ifndef UEFI + struct E820 *p = (struct E820 *)0xffff800000007e00; + for(i = 0;i < 32;i++) +#else + struct EFI_E820_MEMORY_DESCRIPTOR *p = (struct EFI_E820_MEMORY_DESCRIPTOR *)boot_para_info->E820_Info.E820_Entry; for(i = 0;i < boot_para_info->E820_Info.E820_Entry_count;i++) +#endif { - color_printk(GREEN,BLACK,"UEFI---Address:%#018lx\tLength:%#018lx\tType:%#010x\n",p->address,p->length,p->type); + if(p->type == 1) + color_printk(ORANGE,BLACK,"Address:%#018lx\tLength:%#018lx\tType:%#010x\n",p->address,p->length,p->type); if(p->type == 1) TotalMem += p->length; - +#ifndef UEFI + memory_management_struct.e820[i].address = p->address; + memory_management_struct.e820[i].length = p->length; +#else memory_management_struct.e820[i].address += p->address; memory_management_struct.e820[i].length += p->length; - memory_management_struct.e820[i].type = p->type; +#endif + memory_management_struct.e820[i].type = p->type; + memory_management_struct.e820_length = i; p++; @@ -111,7 +133,6 @@ void init_memory() for(i = 0;i <= memory_management_struct.e820_length;i++) { unsigned long start,end; - color_printk(ORANGE,BLACK,"KERN---Address:%#018lx\tLength:%#018lx\tType:%#010x\n",memory_management_struct.e820[i].address,memory_management_struct.e820[i].length,memory_management_struct.e820[i].type); if(memory_management_struct.e820[i].type != 1) continue; start = PAGE_2M_ALIGN(memory_management_struct.e820[i].address); @@ -121,13 +142,13 @@ void init_memory() TotalMem += (end - start) >> PAGE_2M_SHIFT; } - color_printk(ORANGE,BLACK,"OS Can Used Total 2M PAGEs:%#010x=%010d\n",TotalMem,TotalMem); + color_printk(ORANGE,BLACK,"OS Can Used Total 2M PAGEs:%#018lx=%018ld\n",TotalMem,TotalMem); TotalMem = memory_management_struct.e820[memory_management_struct.e820_length].address + memory_management_struct.e820[memory_management_struct.e820_length].length; //bits map construction init - memory_management_struct.bits_map = (unsigned long *)((memory_management_struct.end_brk + PAGE_4K_SIZE - 1) & PAGE_4K_MASK); + memory_management_struct.bits_map = (unsigned long *)((memory_management_struct.start_brk + PAGE_4K_SIZE - 1) & PAGE_4K_MASK); memory_management_struct.bits_size = TotalMem >> PAGE_2M_SHIFT; @@ -155,14 +176,11 @@ void init_memory() memset(memory_management_struct.zones_struct,0x00,memory_management_struct.zones_length); //init zones memory - - for(i = 0;i <= memory_management_struct.e820_length;i++) { unsigned long start,end; struct Zone * z; struct Page * p; - unsigned long * b; if(memory_management_struct.e820[i].type != 1) continue; @@ -204,9 +222,7 @@ void init_memory() p->age = 0; *(memory_management_struct.bits_map + ((p->PHY_address >> PAGE_2M_SHIFT) >> 6)) ^= 1UL << (p->PHY_address >> PAGE_2M_SHIFT) % 64; - - } - + } } /////////////init address 0 to page struct 0; because the memory_management_struct.e820[0].type != 1 @@ -214,10 +230,11 @@ void init_memory() memory_management_struct.pages_struct->zone_struct = memory_management_struct.zones_struct; memory_management_struct.pages_struct->PHY_address = 0UL; - memory_management_struct.pages_struct->attribute = 0; - memory_management_struct.pages_struct->reference_count = 0; - memory_management_struct.pages_struct->age = 0; + set_page_attribute(memory_management_struct.pages_struct,PG_PTable_Maped | PG_Kernel_Init | PG_Kernel); + memory_management_struct.pages_struct->reference_count = 1; + memory_management_struct.pages_struct->age = 0; + ///////////// memory_management_struct.zones_length = (memory_management_struct.zones_size * sizeof(struct Zone) + sizeof(long) - 1) & ( ~ (sizeof(long) - 1)); @@ -228,50 +245,54 @@ void init_memory() color_printk(ORANGE,BLACK,"zones_struct:%#018lx,zones_size:%#018lx,zones_length:%#018lx\n",memory_management_struct.zones_struct,memory_management_struct.zones_size,memory_management_struct.zones_length); - ZONE_DMA_INDEX = 0; //need rewrite in the future - ZONE_NORMAL_INDEX = 0; //need rewrite in the future - - for(i = 0;i < memory_management_struct.zones_size;i++) //need rewrite in the future + ZONE_DMA_INDEX = 0; + ZONE_NORMAL_INDEX = 0; + ZONE_UNMAPED_INDEX = 0; + + for(i = 0;i < memory_management_struct.zones_size;i++) { struct Zone * z = memory_management_struct.zones_struct + i; color_printk(ORANGE,BLACK,"zone_start_address:%#018lx,zone_end_address:%#018lx,zone_length:%#018lx,pages_group:%#018lx,pages_length:%#018lx\n",z->zone_start_address,z->zone_end_address,z->zone_length,z->pages_group,z->pages_length); - if(z->zone_start_address == 0x100000000) + if(z->zone_start_address >= 0x100000000 && !ZONE_UNMAPED_INDEX) ZONE_UNMAPED_INDEX = i; } + color_printk(ORANGE,BLACK,"ZONE_DMA_INDEX:%d\tZONE_NORMAL_INDEX:%d\tZONE_UNMAPED_INDEX:%d\n",ZONE_DMA_INDEX,ZONE_NORMAL_INDEX,ZONE_UNMAPED_INDEX); + memory_management_struct.end_of_struct = (unsigned long)((unsigned long)memory_management_struct.zones_struct + memory_management_struct.zones_length + sizeof(long) * 32) & ( ~ (sizeof(long) - 1)); ////need a blank to separate memory_management_struct - color_printk(ORANGE,BLACK,"start_code:%#018lx,end_code:%#018lx,end_data:%#018lx,end_brk:%#018lx,end_of_struct:%#018lx\n",memory_management_struct.start_code,memory_management_struct.end_code,memory_management_struct.end_data,memory_management_struct.end_brk, memory_management_struct.end_of_struct); - + color_printk(ORANGE,BLACK,"start_code:%#018lx,end_code:%#018lx,end_data:%#018lx,start_brk:%#018lx,end_of_struct:%#018lx\n",memory_management_struct.start_code,memory_management_struct.end_code,memory_management_struct.end_data,memory_management_struct.start_brk, memory_management_struct.end_of_struct); i = Virt_To_Phy(memory_management_struct.end_of_struct) >> PAGE_2M_SHIFT; - for(j = 0;j <= i;j++) + for(j = 1;j <= i;j++) { - page_init(memory_management_struct.pages_struct + j,PG_PTable_Maped | PG_Kernel_Init | PG_Active | PG_Kernel); + struct Page * tmp_page = memory_management_struct.pages_struct + j; + page_init(tmp_page,PG_PTable_Maped | PG_Kernel_Init | PG_Kernel); + *(memory_management_struct.bits_map + ((tmp_page->PHY_address >> PAGE_2M_SHIFT) >> 6)) |= 1UL << (tmp_page->PHY_address >> PAGE_2M_SHIFT) % 64; + tmp_page->zone_struct->page_using_count++; + tmp_page->zone_struct->page_free_count--; } + tmp = Get_gdt(); -// Global_CR3 = Get_gdt(); - -// color_printk(INDIGO,BLACK,"Global_CR3\t:%#018lx\n",Global_CR3); -// color_printk(INDIGO,BLACK,"*Global_CR3\t:%#018lx\n",*Phy_To_Virt(Global_CR3) & (~0xff)); -// color_printk(PURPLE,BLACK,"**Global_CR3\t:%#018lx\n",*Phy_To_Virt(*Phy_To_Virt(Global_CR3) & (~0xff)) & (~0xff)); + color_printk(INDIGO,BLACK,"tmp\t:%#018lx\n",tmp); + color_printk(INDIGO,BLACK,"*tmp\t:%#018lx\n",*Phy_To_Virt(tmp) & (~0xff)); + color_printk(PURPLE,BLACK,"**tmp\t:%#018lx\n",*Phy_To_Virt(*Phy_To_Virt(tmp) & (~0xff)) & (~0xff)); + color_printk(ORANGE,BLACK,"1.memory_management_struct.bits_map:%#018lx\tzone_struct->page_using_count:%d\tzone_struct->page_free_count:%d\n",*memory_management_struct.bits_map,memory_management_struct.zones_struct->page_using_count,memory_management_struct.zones_struct->page_free_count); // for(i = 0;i < 10;i++) // *(Phy_To_Virt(Global_CR3) + i) = 0UL; - + flush_tlb(); } /* number: number < 64 - zone_select: zone select from dma , mapped in pagetable , unmapped in pagetable - page_flags: struct Page flages */ @@ -280,41 +301,48 @@ struct Page * alloc_pages(int zone_select,int number,unsigned long page_flags) { int i; unsigned long page = 0; + unsigned long attribute = 0; int zone_start = 0; int zone_end = 0; + + if(number >= 64 || number <= 0) + { + color_printk(RED,BLACK,"alloc_pages() ERROR: number is invalid\n"); + return NULL; + } switch(zone_select) { case ZONE_DMA: zone_start = 0; zone_end = ZONE_DMA_INDEX; - + attribute = PG_PTable_Maped; break; case ZONE_NORMAL: zone_start = ZONE_DMA_INDEX; zone_end = ZONE_NORMAL_INDEX; - + attribute = PG_PTable_Maped; break; case ZONE_UNMAPED: zone_start = ZONE_UNMAPED_INDEX; zone_end = memory_management_struct.zones_size - 1; - + attribute = 0; break; default: - color_printk(RED,BLACK,"alloc_pages error zone_select index\n"); + color_printk(RED,BLACK,"alloc_pages() ERROR: zone_select index is invalid\n"); return NULL; break; } - for(i = zone_start;i <= zone_end; i++) + for(i = zone_start; i <= zone_end; i++) { struct Zone * z; unsigned long j; - unsigned long start,end,length; + unsigned long start,end; unsigned long tmp; if((memory_management_struct.zones_struct + i)->page_free_count < number) @@ -323,33 +351,39 @@ struct Page * alloc_pages(int zone_select,int number,unsigned long page_flags) z = memory_management_struct.zones_struct + i; start = z->zone_start_address >> PAGE_2M_SHIFT; end = z->zone_end_address >> PAGE_2M_SHIFT; - length = z->zone_length >> PAGE_2M_SHIFT; tmp = 64 - start % 64; - for(j = start;j <= end;j += j % 64 ? tmp : 64) + for(j = start;j < end;j += j % 64 ? tmp : 64) { unsigned long * p = memory_management_struct.bits_map + (j >> 6); + unsigned long k = 0; unsigned long shift = j % 64; - unsigned long k; - for(k = shift;k < 64 - shift;k++) + + unsigned long num = (1UL << number) - 1; + + for(k = shift;k < 64;k++) { - if( !(((*p >> k) | (*(p + 1) << (64 - k))) & (number == 64 ? 0xffffffffffffffffUL : ((1UL << number) - 1))) ) + if( !( (k ? ((*p >> k) | (*(p + 1) << (64 - k))) : *p) & (num) ) ) { unsigned long l; - page = j + k - 1; + page = j + k - shift; for(l = 0;l < number;l++) { - struct Page * x = memory_management_struct.pages_struct + page + l; - page_init(x,page_flags); + struct Page * pageptr = memory_management_struct.pages_struct + page + l; + + *(memory_management_struct.bits_map + ((pageptr->PHY_address >> PAGE_2M_SHIFT) >> 6)) |= 1UL << (pageptr->PHY_address >> PAGE_2M_SHIFT) % 64; + z->page_using_count++; + z->page_free_count--; + pageptr->attribute = attribute; } goto find_free_pages; } } - } } + color_printk(RED,BLACK,"alloc_pages() ERROR: no page can alloc\n"); return NULL; find_free_pages: @@ -357,3 +391,769 @@ find_free_pages: return (struct Page *)(memory_management_struct.pages_struct + page); } +/* + + page: free page start from this pointer + number: number < 64 + +*/ + +void free_pages(struct Page * page,int number) +{ + int i = 0; + + if(page == NULL) + { + color_printk(RED,BLACK,"free_pages() ERROR: page is invalid\n"); + return ; + } + + if(number >= 64 || number <= 0) + { + color_printk(RED,BLACK,"free_pages() ERROR: number is invalid\n"); + return ; + } + + for(i = 0;iPHY_address >> PAGE_2M_SHIFT) >> 6)) &= ~(1UL << (page->PHY_address >> PAGE_2M_SHIFT) % 64); + page->zone_struct->page_using_count--; + page->zone_struct->page_free_count++; + page->attribute = 0; + } +} + +/* + return virtual kernel address + gfp_flages: the condition of get memory +*/ + +void * kmalloc(unsigned long size,unsigned long gfp_flages) +{ + int i,j; + struct Slab * slab = NULL; + if(size > 1048576) + { + color_printk(RED,BLACK,"kmalloc() ERROR: kmalloc size too long:%08d\n",size); + return NULL; + } + for(i = 0;i < 16;i++) + if(kmalloc_cache_size[i].size >= size) + break; + slab = kmalloc_cache_size[i].cache_pool; + + if(kmalloc_cache_size[i].total_free != 0) + { + do + { + if(slab->free_count == 0) + slab = container_of(list_next(&slab->list),struct Slab,list); + else + break; + }while(slab != kmalloc_cache_size[i].cache_pool); + } + else + { + slab = kmalloc_create(kmalloc_cache_size[i].size); + + if(slab == NULL) + { + color_printk(BLUE,BLACK,"kmalloc()->kmalloc_create()=>slab == NULL\n"); + return NULL; + } + + kmalloc_cache_size[i].total_free += slab->color_count; + + color_printk(BLUE,BLACK,"kmalloc()->kmalloc_create()<=size:%#010x\n",kmalloc_cache_size[i].size);/////// + + list_add_to_before(&kmalloc_cache_size[i].cache_pool->list,&slab->list); + } + + for(j = 0;j < slab->color_count;j++) + { + if(*(slab->color_map + (j >> 6)) == 0xffffffffffffffffUL) + { + j += 63; + continue; + } + + if( (*(slab->color_map + (j >> 6)) & (1UL << (j % 64))) == 0 ) + { + *(slab->color_map + (j >> 6)) |= 1UL << (j % 64); + slab->using_count++; + slab->free_count--; + + kmalloc_cache_size[i].total_free--; + kmalloc_cache_size[i].total_using++; + + return (void *)((char *)slab->Vaddress + kmalloc_cache_size[i].size * j); + } + } + + color_printk(BLUE,BLACK,"kmalloc() ERROR: no memory can alloc\n"); + return NULL; +} + +/* + +*/ + +struct Slab * kmalloc_create(unsigned long size) +{ + int i; + struct Slab * slab = NULL; + struct Page * page = NULL; + unsigned long * vaddresss = NULL; + long structsize = 0; + + page = alloc_pages(ZONE_NORMAL,1, 0); + + if(page == NULL) + { + color_printk(RED,BLACK,"kmalloc_create()->alloc_pages()=>page == NULL\n"); + return NULL; + } + + page_init(page,PG_Kernel); + + switch(size) + { + ////////////////////slab + map in 2M page + + case 32: + case 64: + case 128: + case 256: + case 512: + + vaddresss = Phy_To_Virt(page->PHY_address); + structsize = sizeof(struct Slab) + PAGE_2M_SIZE / size / 8; + + slab = (struct Slab *)((unsigned char *)vaddresss + PAGE_2M_SIZE - structsize); + slab->color_map = (unsigned long *)((unsigned char *)slab + sizeof(struct Slab)); + + slab->free_count = (PAGE_2M_SIZE - (PAGE_2M_SIZE / size / 8) - sizeof(struct Slab)) / size; + slab->using_count = 0; + slab->color_count = slab->free_count; + slab->Vaddress = vaddresss; + slab->page = page; + list_init(&slab->list); + + slab->color_length = ((slab->color_count + sizeof(unsigned long) * 8 - 1) >> 6) << 3; + memset(slab->color_map,0xff,slab->color_length); + + for(i = 0;i < slab->color_count;i++) + *(slab->color_map + (i >> 6)) ^= 1UL << i % 64; + + break; + + ///////////////////kmalloc slab and map,not in 2M page anymore + + case 1024: //1KB + case 2048: + case 4096: //4KB + case 8192: + case 16384: + + //////////////////color_map is a very short buffer. + + case 32768: + case 65536: + case 131072: //128KB + case 262144: + case 524288: + case 1048576: //1MB + + slab = (struct Slab *)kmalloc(sizeof(struct Slab),0); + + slab->free_count = PAGE_2M_SIZE / size; + slab->using_count = 0; + slab->color_count = slab->free_count; + + slab->color_length = ((slab->color_count + sizeof(unsigned long) * 8 - 1) >> 6) << 3; + + slab->color_map = (unsigned long *)kmalloc(slab->color_length,0); + memset(slab->color_map,0xff,slab->color_length); + + slab->Vaddress = Phy_To_Virt(page->PHY_address); + slab->page = page; + list_init(&slab->list); + + for(i = 0;i < slab->color_count;i++) + *(slab->color_map + (i >> 6)) ^= 1UL << i % 64; + + break; + + default: + + color_printk(RED,BLACK,"kmalloc_create() ERROR: wrong size:%08d\n",size); + free_pages(page,1); + + return NULL; + } + + return slab; +} + +/* + +*/ + +unsigned long kfree(void * address) +{ + int i; + int index; + struct Slab * slab = NULL; + void * page_base_address = (void *)((unsigned long)address & PAGE_2M_MASK); + + for(i = 0;i < 16;i++) + { + slab = kmalloc_cache_size[i].cache_pool; + do + { + if(slab->Vaddress == page_base_address) + { + index = (address - slab->Vaddress) / kmalloc_cache_size[i].size; + + *(slab->color_map + (index >> 6)) ^= 1UL << index % 64; + + slab->free_count++; + slab->using_count--; + + kmalloc_cache_size[i].total_free++; + kmalloc_cache_size[i].total_using--; + + if((slab->using_count == 0) && (kmalloc_cache_size[i].total_free >= slab->color_count * 3 / 2) && (kmalloc_cache_size[i].cache_pool != slab)) + { + switch(kmalloc_cache_size[i].size) + { + ////////////////////slab + map in 2M page + + case 32: + case 64: + case 128: + case 256: + case 512: + list_del(&slab->list); + kmalloc_cache_size[i].total_free -= slab->color_count; + + page_clean(slab->page); + free_pages(slab->page,1); + break; + + default: + list_del(&slab->list); + kmalloc_cache_size[i].total_free -= slab->color_count; + + kfree(slab->color_map); + + page_clean(slab->page); + free_pages(slab->page,1); + kfree(slab); + break; + } + + } + + return 1; + } + else + slab = container_of(list_next(&slab->list),struct Slab,list); + + }while(slab != kmalloc_cache_size[i].cache_pool); + + } + + color_printk(RED,BLACK,"kfree() ERROR: can`t free memory\n"); + + return 0; +} + +/* + +*/ + +struct Slab_cache * slab_create(unsigned long size,void *(* constructor)(void * Vaddress,unsigned long arg),void *(* destructor)(void * Vaddress,unsigned long arg),unsigned long arg) +{ + struct Slab_cache * slab_cache = NULL; + + slab_cache = (struct Slab_cache *)kmalloc(sizeof(struct Slab_cache),0); + + if(slab_cache == NULL) + { + color_printk(RED,BLACK,"slab_create()->kmalloc()=>slab_cache == NULL\n"); + return NULL; + } + + memset(slab_cache,0,sizeof(struct Slab_cache)); + + slab_cache->size = SIZEOF_LONG_ALIGN(size); + slab_cache->total_using = 0; + slab_cache->total_free = 0; + slab_cache->cache_pool = (struct Slab *)kmalloc(sizeof(struct Slab),0); + + if(slab_cache->cache_pool == NULL) + { + color_printk(RED,BLACK,"slab_create()->kmalloc()=>slab_cache->cache_pool == NULL\n"); + kfree(slab_cache); + return NULL; + } + + memset(slab_cache->cache_pool,0,sizeof(struct Slab)); + + slab_cache->cache_dma_pool = NULL; + slab_cache->constructor = constructor; + slab_cache->destructor = destructor; + + list_init(&slab_cache->cache_pool->list); + + slab_cache->cache_pool->page = alloc_pages(ZONE_NORMAL,1,0); + + if(slab_cache->cache_pool->page == NULL) + { + color_printk(RED,BLACK,"slab_create()->alloc_pages()=>slab_cache->cache_pool->page == NULL\n"); + kfree(slab_cache->cache_pool); + kfree(slab_cache); + return NULL; + } + + page_init(slab_cache->cache_pool->page,PG_Kernel); + + slab_cache->cache_pool->using_count = 0; + + slab_cache->cache_pool->free_count = PAGE_2M_SIZE/slab_cache->size; + + slab_cache->total_free = slab_cache->cache_pool->free_count; + + slab_cache->cache_pool->Vaddress = Phy_To_Virt(slab_cache->cache_pool->page->PHY_address); + + slab_cache->cache_pool->color_count = slab_cache->cache_pool->free_count; + + slab_cache->cache_pool->color_length = ((slab_cache->cache_pool->color_count + sizeof(unsigned long) * 8 - 1) >> 6) << 3; + + slab_cache->cache_pool->color_map = (unsigned long *)kmalloc(slab_cache->cache_pool->color_length,0); + + if(slab_cache->cache_pool->color_map == NULL) + { + color_printk(RED,BLACK,"slab_create()->kmalloc()=>slab_cache->cache_pool->color_map == NULL\n"); + + free_pages(slab_cache->cache_pool->page,1); + kfree(slab_cache->cache_pool); + kfree(slab_cache); + return NULL; + } + + memset(slab_cache->cache_pool->color_map,0,slab_cache->cache_pool->color_length); + + return slab_cache; +} + +/* + +*/ + +unsigned long slab_destroy(struct Slab_cache * slab_cache) +{ + struct Slab * slab_p = slab_cache->cache_pool; + struct Slab * tmp_slab = NULL; + + if(slab_cache->total_using != 0) + { + color_printk(RED,BLACK,"slab_cache->total_using != 0\n"); + return 0; + } + + while(!list_is_empty(&slab_p->list)) + { + tmp_slab = slab_p; + slab_p = container_of(list_next(&slab_p->list),struct Slab,list); + + list_del(&tmp_slab->list); + kfree(tmp_slab->color_map); + + page_clean(tmp_slab->page); + free_pages(tmp_slab->page,1); + kfree(tmp_slab); + } + + kfree(slab_p->color_map); + + page_clean(slab_p->page); + free_pages(slab_p->page,1); + kfree(slab_p); + + kfree(slab_cache); + + return 1; +} + +/* + +*/ + +void * slab_malloc(struct Slab_cache * slab_cache,unsigned long arg) +{ + struct Slab * slab_p = slab_cache->cache_pool; + struct Slab * tmp_slab = NULL; + int j = 0; + + if(slab_cache->total_free == 0) + { + tmp_slab = (struct Slab *)kmalloc(sizeof(struct Slab),0); + + if(tmp_slab == NULL) + { + color_printk(RED,BLACK,"slab_malloc()->kmalloc()=>tmp_slab == NULL\n"); + return NULL; + } + + memset(tmp_slab,0,sizeof(struct Slab)); + + list_init(&tmp_slab->list); + + tmp_slab->page = alloc_pages(ZONE_NORMAL,1,0); + + if(tmp_slab->page == NULL) + { + color_printk(RED,BLACK,"slab_malloc()->alloc_pages()=>tmp_slab->page == NULL\n"); + kfree(tmp_slab); + return NULL; + } + + page_init(tmp_slab->page,PG_Kernel); + + tmp_slab->using_count = 0; + tmp_slab->free_count = PAGE_2M_SIZE/slab_cache->size; + tmp_slab->Vaddress = Phy_To_Virt(tmp_slab->page->PHY_address); + + tmp_slab->color_count = tmp_slab->free_count; + tmp_slab->color_length = ((tmp_slab->color_count + sizeof(unsigned long) * 8 - 1) >> 6) << 3; + tmp_slab->color_map = (unsigned long *)kmalloc(tmp_slab->color_length,0); + + if(tmp_slab->color_map == NULL) + { + color_printk(RED,BLACK,"slab_malloc()->kmalloc()=>tmp_slab->color_map == NULL\n"); + free_pages(tmp_slab->page,1); + kfree(tmp_slab); + return NULL; + } + + memset(tmp_slab->color_map,0,tmp_slab->color_length); + + list_add_to_behind(&slab_cache->cache_pool->list,&tmp_slab->list); + + slab_cache->total_free += tmp_slab->color_count; + + for(j = 0;j < tmp_slab->color_count;j++) + { + if( (*(tmp_slab->color_map + (j >> 6)) & (1UL << (j % 64))) == 0 ) + { + *(tmp_slab->color_map + (j >> 6)) |= 1UL << (j % 64); + + tmp_slab->using_count++; + tmp_slab->free_count--; + + slab_cache->total_using++; + slab_cache->total_free--; + + if(slab_cache->constructor != NULL) + { + return slab_cache->constructor((char *)tmp_slab->Vaddress + slab_cache->size * j,arg); + } + else + { + return (void *)((char *)tmp_slab->Vaddress + slab_cache->size * j); + } + } + } + } + else + { + do + { + if(slab_p->free_count == 0) + { + slab_p = container_of(list_next(&slab_p->list),struct Slab,list); + continue; + } + + for(j = 0;j < slab_p->color_count;j++) + { + + if(*(slab_p->color_map + (j >> 6)) == 0xffffffffffffffffUL) + { + j += 63; + continue; + } + + if( (*(slab_p->color_map + (j >> 6)) & (1UL << (j % 64))) == 0 ) + { + *(slab_p->color_map + (j >> 6)) |= 1UL << (j % 64); + + slab_p->using_count++; + slab_p->free_count--; + + slab_cache->total_using++; + slab_cache->total_free--; + + if(slab_cache->constructor != NULL) + { + return slab_cache->constructor((char *)slab_p->Vaddress + slab_cache->size * j,arg); + } + else + { + return (void *)((char *)slab_p->Vaddress + slab_cache->size * j); + } + } + } + }while(slab_p != slab_cache->cache_pool); + } + + color_printk(RED,BLACK,"slab_malloc() ERROR: can`t alloc\n"); + if(tmp_slab != NULL) + { + list_del(&tmp_slab->list); + kfree(tmp_slab->color_map); + page_clean(tmp_slab->page); + free_pages(tmp_slab->page,1); + kfree(tmp_slab); + } + + return NULL; +} + +/* + +*/ + +unsigned long slab_free(struct Slab_cache * slab_cache,void * address,unsigned long arg) +{ + + struct Slab * slab_p = slab_cache->cache_pool; + int index = 0; + + do + { + if(slab_p->Vaddress <= address && address < slab_p->Vaddress + PAGE_2M_SIZE) + { + index = (address - slab_p->Vaddress) / slab_cache->size; + *(slab_p->color_map + (index >> 6)) ^= 1UL << index % 64; + slab_p->free_count++; + slab_p->using_count--; + + slab_cache->total_using--; + slab_cache->total_free++; + + if(slab_cache->destructor != NULL) + { + slab_cache->destructor((char *)slab_p->Vaddress + slab_cache->size * index,arg); + } + + if((slab_p->using_count == 0) && (slab_cache->total_free >= slab_p->color_count * 3 / 2)) + { + list_del(&slab_p->list); + slab_cache->total_free -= slab_p->color_count; + + kfree(slab_p->color_map); + + page_clean(slab_p->page); + free_pages(slab_p->page,1); + kfree(slab_p); + } + + return 1; + } + else + { + slab_p = container_of(list_next(&slab_p->list),struct Slab,list); + continue; + } + + }while(slab_p != slab_cache->cache_pool); + + color_printk(RED,BLACK,"slab_free() ERROR: address not in slab\n"); + + return 0; +} + +/* + +*/ + +unsigned long slab_init() +{ + struct Page * page = NULL; + unsigned long * virtual = NULL; // get a free page and set to empty page table and return the virtual address + unsigned long i,j; + + unsigned long tmp_address = memory_management_struct.end_of_struct; + + for(i = 0;i < 16;i++) + { + kmalloc_cache_size[i].cache_pool = (struct Slab *)memory_management_struct.end_of_struct; + memory_management_struct.end_of_struct = memory_management_struct.end_of_struct + sizeof(struct Slab) + sizeof(long) * 10; + + list_init(&kmalloc_cache_size[i].cache_pool->list); + + //////////// init sizeof struct Slab of cache size + + kmalloc_cache_size[i].cache_pool->using_count = 0; + kmalloc_cache_size[i].cache_pool->free_count = PAGE_2M_SIZE / kmalloc_cache_size[i].size; + + kmalloc_cache_size[i].cache_pool->color_length =((PAGE_2M_SIZE / kmalloc_cache_size[i].size + sizeof(unsigned long) * 8 - 1) >> 6) << 3; + + kmalloc_cache_size[i].cache_pool->color_count = kmalloc_cache_size[i].cache_pool->free_count; + + kmalloc_cache_size[i].cache_pool->color_map = (unsigned long *)memory_management_struct.end_of_struct; + + memory_management_struct.end_of_struct = (unsigned long)(memory_management_struct.end_of_struct + kmalloc_cache_size[i].cache_pool->color_length + sizeof(long) * 10) & ( ~ (sizeof(long) - 1)); + + memset(kmalloc_cache_size[i].cache_pool->color_map,0xff,kmalloc_cache_size[i].cache_pool->color_length); + + for(j = 0;j < kmalloc_cache_size[i].cache_pool->color_count;j++) + *(kmalloc_cache_size[i].cache_pool->color_map + (j >> 6)) ^= 1UL << j % 64; + + kmalloc_cache_size[i].total_free = kmalloc_cache_size[i].cache_pool->color_count; + kmalloc_cache_size[i].total_using = 0; + + } + + //////////// init page for kernel code and memory management struct + + i = Virt_To_Phy(memory_management_struct.end_of_struct) >> PAGE_2M_SHIFT; + + for(j = PAGE_2M_ALIGN(Virt_To_Phy(tmp_address)) >> PAGE_2M_SHIFT;j <= i;j++) + { + page = memory_management_struct.pages_struct + j; + *(memory_management_struct.bits_map + ((page->PHY_address >> PAGE_2M_SHIFT) >> 6)) |= 1UL << (page->PHY_address >> PAGE_2M_SHIFT) % 64; + page->zone_struct->page_using_count++; + page->zone_struct->page_free_count--; + page_init(page,PG_PTable_Maped | PG_Kernel_Init | PG_Kernel); + } + + color_printk(ORANGE,BLACK,"2.memory_management_struct.bits_map:%#018lx\tzone_struct->page_using_count:%d\tzone_struct->page_free_count:%d\n",*memory_management_struct.bits_map,memory_management_struct.zones_struct->page_using_count,memory_management_struct.zones_struct->page_free_count); + + for(i = 0;i < 16;i++) + { + virtual = (unsigned long *)((memory_management_struct.end_of_struct + PAGE_2M_SIZE * i + PAGE_2M_SIZE - 1) & PAGE_2M_MASK); + page = Virt_To_2M_Page(virtual); + + *(memory_management_struct.bits_map + ((page->PHY_address >> PAGE_2M_SHIFT) >> 6)) |= 1UL << (page->PHY_address >> PAGE_2M_SHIFT) % 64; + page->zone_struct->page_using_count++; + page->zone_struct->page_free_count--; + + page_init(page,PG_PTable_Maped | PG_Kernel_Init | PG_Kernel); + + kmalloc_cache_size[i].cache_pool->page = page; + kmalloc_cache_size[i].cache_pool->Vaddress = virtual; + } + + color_printk(ORANGE,BLACK,"3.memory_management_struct.bits_map:%#018lx\tzone_struct->page_using_count:%d\tzone_struct->page_free_count:%d\n",*memory_management_struct.bits_map,memory_management_struct.zones_struct->page_using_count,memory_management_struct.zones_struct->page_free_count); + + color_printk(ORANGE,BLACK,"start_code:%#018lx,end_code:%#018lx,end_data:%#018lx,start_brk:%#018lx,end_of_struct:%#018lx\n",memory_management_struct.start_code,memory_management_struct.end_code,memory_management_struct.end_data,memory_management_struct.start_brk, memory_management_struct.end_of_struct); + + return 1; +} + +/* + +*/ + +void pagetable_init() +{ + unsigned long i,j; + unsigned long * tmp = NULL; + + tmp = (unsigned long *)(((unsigned long)Phy_To_Virt((unsigned long)Get_gdt() & (~ 0xfffUL))) + 8 * 256); + +// color_printk(YELLOW,BLACK,"1:%#018lx,%#018lx\t\t\n",(unsigned long)tmp,*tmp); + tmp = Phy_To_Virt(*tmp & (~0xfffUL)); + +// color_printk(YELLOW,BLACK,"2:%#018lx,%#018lx\t\t\n",(unsigned long)tmp,*tmp); + tmp = Phy_To_Virt(*tmp & (~0xfffUL)); +// color_printk(YELLOW,BLACK,"3:%#018lx,%#018lx\t\t\n",(unsigned long)tmp,*tmp); + + for(i = 0;i < memory_management_struct.zones_size;i++) + { + struct Zone * z = memory_management_struct.zones_struct + i; + struct Page * p = z->pages_group; + + if(ZONE_UNMAPED_INDEX && i == ZONE_UNMAPED_INDEX) + break; + + for(j = 0;j < z->pages_length ; j++,p++) + { + + tmp = (unsigned long *)(((unsigned long)Phy_To_Virt((unsigned long)Get_gdt() & (~ 0xfffUL))) + (((unsigned long)Phy_To_Virt(p->PHY_address) >> PAGE_GDT_SHIFT) & 0x1ff) * 8); + + if(*tmp == 0) + { + unsigned long * virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_mpl4t(tmp,mk_mpl4t(Virt_To_Phy(virtual),PAGE_KERNEL_GDT)); + } + + tmp = (unsigned long *)((unsigned long)Phy_To_Virt(*tmp & (~ 0xfffUL)) + (((unsigned long)Phy_To_Virt(p->PHY_address) >> PAGE_1G_SHIFT) & 0x1ff) * 8); + + if(*tmp == 0) + { + unsigned long * virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_pdpt(tmp,mk_pdpt(Virt_To_Phy(virtual),PAGE_KERNEL_Dir)); + } + + tmp = (unsigned long *)((unsigned long)Phy_To_Virt(*tmp & (~ 0xfffUL)) + (((unsigned long)Phy_To_Virt(p->PHY_address) >> PAGE_2M_SHIFT) & 0x1ff) * 8); + + set_pdt(tmp,mk_pdt(p->PHY_address,PAGE_KERNEL_Page)); + +// if(j % 50 == 0) +// color_printk(GREEN,BLACK,"@:%#018lx,%#018lx\t\n",(unsigned long)tmp,*tmp); + } + } + + flush_tlb(); +} + +unsigned long do_brk(unsigned long addr,unsigned long len) +{ + unsigned long * tmp = NULL; + unsigned long * virtual = NULL; + struct Page * p = NULL; + unsigned long i = 0; + + for(i = addr;i < addr + len;i += PAGE_2M_SIZE) + { + tmp = Phy_To_Virt((unsigned long *)((unsigned long)current->mm->pgd & (~ 0xfffUL)) + ((i >> PAGE_GDT_SHIFT) & 0x1ff)); + if(*tmp == NULL) + { + virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_mpl4t(tmp,mk_mpl4t(Virt_To_Phy(virtual),PAGE_USER_GDT)); + } + + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + ((i >> PAGE_1G_SHIFT) & 0x1ff)); + if(*tmp == NULL) + { + virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_pdpt(tmp,mk_pdpt(Virt_To_Phy(virtual),PAGE_USER_Dir)); + } + + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + ((i >> PAGE_2M_SHIFT) & 0x1ff)); + if(*tmp == NULL) + { + p = alloc_pages(ZONE_NORMAL,1,PG_PTable_Maped); + if(p == NULL) + return -ENOMEM; + set_pdt(tmp,mk_pdt(p->PHY_address,PAGE_USER_Page)); + } + } + + current->mm->end_brk = i; + + flush_tlb(); + + return i; +} + + diff --git a/kernel/memory.h b/kernel/memory.h index ebb5530a1a7ee7960ca96c33d35d948d1daaa044..e6bcbf953c9f7c779506984036ec8a9c5fda9d46 100644 --- a/kernel/memory.h +++ b/kernel/memory.h @@ -8,9 +8,9 @@ ***************************************************/ #ifndef __MEMORY_H__ + #define __MEMORY_H__ -#include "UEFI_boot_param_info.h" #include "lib.h" // 8Bytes per cell @@ -21,6 +21,7 @@ */ #define PAGE_OFFSET ((unsigned long)0xffff800000000000) +#define TASK_SIZE ((unsigned long)0x00007fffffffffff) #define PAGE_GDT_SHIFT 39 #define PAGE_1G_SHIFT 30 @@ -42,41 +43,40 @@ #define Virt_To_2M_Page(kaddr) (memory_management_struct.pages_struct + (Virt_To_Phy(kaddr) >> PAGE_2M_SHIFT)) #define Phy_to_2M_Page(kaddr) (memory_management_struct.pages_struct + ((unsigned long)(kaddr) >> PAGE_2M_SHIFT)) - ////page table attribute // bit 63 Execution Disable: -#define PAGE_XD (unsigned long)0x1000000000000000 +#define PAGE_XD (1UL << 63) // bit 12 Page Attribute Table -#define PAGE_PAT (unsigned long)0x1000 +#define PAGE_PAT (1UL << 12) // bit 8 Global Page:1,global;0,part -#define PAGE_Global (unsigned long)0x0100 +#define PAGE_Global (1UL << 8) // bit 7 Page Size:1,big page;0,small page; -#define PAGE_PS (unsigned long)0x0080 +#define PAGE_PS (1UL << 7) // bit 6 Dirty:1,dirty;0,clean; -#define PAGE_Dirty (unsigned long)0x0040 +#define PAGE_Dirty (1UL << 6) // bit 5 Accessed:1,visited;0,unvisited; -#define PAGE_Accessed (unsigned long)0x0020 +#define PAGE_Accessed (1UL << 5) // bit 4 Page Level Cache Disable -#define PAGE_PCD (unsigned long)0x0010 +#define PAGE_PCD (1UL << 4) // bit 3 Page Level Write Through -#define PAGE_PWT (unsigned long)0x0008 +#define PAGE_PWT (1UL << 3) // bit 2 User Supervisor:1,user and supervisor;0,supervisor; -#define PAGE_U_S (unsigned long)0x0004 +#define PAGE_U_S (1UL << 2) // bit 1 Read Write:1,read and write;0,read; -#define PAGE_R_W (unsigned long)0x0002 +#define PAGE_R_W (1UL << 1) // bit 0 Present:1,present;0,no present; -#define PAGE_Present (unsigned long)0x0001 +#define PAGE_Present (1UL << 0) //1,0 #define PAGE_KERNEL_GDT (PAGE_R_W | PAGE_Present) @@ -87,6 +87,9 @@ //7,1,0 #define PAGE_KERNEL_Page (PAGE_PS | PAGE_R_W | PAGE_Present) +//1,0 +#define PAGE_USER_GDT (PAGE_U_S | PAGE_R_W | PAGE_Present) + //2,1,0 #define PAGE_USER_Dir (PAGE_U_S | PAGE_R_W | PAGE_Present) @@ -101,28 +104,33 @@ typedef struct {unsigned long pml4t;} pml4t_t; #define mk_mpl4t(addr,attr) ((unsigned long)(addr) | (unsigned long)(attr)) #define set_mpl4t(mpl4tptr,mpl4tval) (*(mpl4tptr) = (mpl4tval)) - typedef struct {unsigned long pdpt;} pdpt_t; #define mk_pdpt(addr,attr) ((unsigned long)(addr) | (unsigned long)(attr)) #define set_pdpt(pdptptr,pdptval) (*(pdptptr) = (pdptval)) - typedef struct {unsigned long pdt;} pdt_t; #define mk_pdt(addr,attr) ((unsigned long)(addr) | (unsigned long)(attr)) #define set_pdt(pdtptr,pdtval) (*(pdtptr) = (pdtval)) - typedef struct {unsigned long pt;} pt_t; #define mk_pt(addr,attr) ((unsigned long)(addr) | (unsigned long)(attr)) #define set_pt(ptptr,ptval) (*(ptptr) = (ptval)) + +struct E820 +{ + unsigned long address; + unsigned long length; + unsigned int type; +}__attribute__((packed)); + /* */ struct Global_Memory_Descriptor { - struct EFI_E820_MEMORY_DESCRIPTOR e820[32]; + struct E820 e820[32]; unsigned long e820_length; unsigned long * bits_map; @@ -137,7 +145,7 @@ struct Global_Memory_Descriptor unsigned long zones_size; unsigned long zones_length; - unsigned long start_code , end_code , end_data , end_brk; + unsigned long start_code , end_code , end_data , end_rodata , start_brk; unsigned long end_of_struct; }; @@ -153,37 +161,23 @@ struct Global_Memory_Descriptor // #define ZONE_UNMAPED (1 << 2) -////struct page attribute (alloc_pages flags) +////struct page attribute -// +// mapped=1 or un-mapped=0 #define PG_PTable_Maped (1 << 0) -// +// init-code=1 or normal-code/data=0 #define PG_Kernel_Init (1 << 1) -// -#define PG_Referenced (1 << 2) - -// -#define PG_Dirty (1 << 3) - -// -#define PG_Active (1 << 4) - -// -#define PG_Up_To_Date (1 << 5) +// device=1 or memory=0 +#define PG_Device (1 << 2) -// -#define PG_Device (1 << 6) +// kernel=1 or user=0 +#define PG_Kernel (1 << 3) -// -#define PG_Kernel (1 << 7) +// shared=1 or single-use=0 +#define PG_Shared (1 << 4) -// -#define PG_K_Share_To_U (1 << 8) - -// -#define PG_Slab (1 << 9) struct Page { @@ -196,6 +190,12 @@ struct Page unsigned long age; }; +//// each zone index + +int ZONE_DMA_INDEX = 0; +int ZONE_NORMAL_INDEX = 0; //low 1GB RAM ,was mapped in pagetable +int ZONE_UNMAPED_INDEX = 0; //above 1GB RAM,unmapped in pagetable + #define MAX_NR_ZONES 10 //max zone /* @@ -220,16 +220,47 @@ struct Zone unsigned long total_pages_link; }; - extern struct Global_Memory_Descriptor memory_management_struct; -unsigned long page_init(struct Page * page,unsigned long flags); +/* -unsigned long page_clean(struct Page * page); +*/ -void init_memory(); +struct Slab +{ + struct List list; + struct Page * page; -struct Page * alloc_pages(int zone_select,int number,unsigned long page_flags); + unsigned long using_count; + unsigned long free_count; + + void * Vaddress; + + unsigned long color_length; + unsigned long color_count; + + unsigned long * color_map; +}; + +struct Slab_cache +{ + unsigned long size; + unsigned long total_using; + unsigned long total_free; + struct Slab * cache_pool; + struct Slab * cache_dma_pool; + void *(* constructor)(void * Vaddress,unsigned long arg); + void *(* destructor)(void * Vaddress,unsigned long arg); +}; + +/* + kmalloc`s struct +*/ + +extern struct Slab_cache kmalloc_cache_size[16]; + +#define SIZEOF_LONG_ALIGN(size) ((size + sizeof(long) - 1) & ~(sizeof(long) - 1) ) +#define SIZEOF_INT_ALIGN(size) ((size + sizeof(int) - 1) & ~(sizeof(int) - 1) ) /* @@ -270,5 +301,90 @@ inline unsigned long * Get_gdt() return tmp; } +/* + +*/ + +unsigned long page_init(struct Page * page,unsigned long flags); + +unsigned long page_clean(struct Page * page); + +/* + +*/ + +unsigned long get_page_attribute(struct Page * page); + +unsigned long set_page_attribute(struct Page * page,unsigned long flags); + +/* + +*/ + +void init_memory(); + +/* + +*/ + +struct Page * alloc_pages(int zone_select,int number,unsigned long page_flags); + +void free_pages(struct Page * page,int number); + +/* + return virtual kernel address +*/ + +void * kmalloc(unsigned long size,unsigned long flags); + +/* + +*/ + +struct Slab * kmalloc_create(unsigned long size); + +/* + +*/ + +unsigned long kfree(void * address); + +/* + +*/ + +struct Slab_cache * slab_create(unsigned long size,void *(* constructor)(void * Vaddress,unsigned long arg),void *(* destructor)(void * Vaddress,unsigned long arg),unsigned long arg); + +/* + +*/ + +unsigned long slab_destroy(struct Slab_cache * slab_cache); + +/* + +*/ + +void * slab_malloc(struct Slab_cache * slab_cache,unsigned long arg); + +/* + +*/ + +unsigned long slab_free(struct Slab_cache * slab_cache,void * address,unsigned long arg); + +/* + +*/ + +unsigned long slab_init(); + +/* + +*/ + +void pagetable_init(); + +unsigned long do_brk(unsigned long addr,unsigned long len); #endif diff --git a/kernel/mouse.c b/kernel/mouse.c new file mode 100644 index 0000000000000000000000000000000000000000..33768a3580f2732757b4d2f1abb362e2e627b173 --- /dev/null +++ b/kernel/mouse.c @@ -0,0 +1,169 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "mouse.h" +#include "keyboard.h" +#include "APIC.h" +#include "memory.h" +#include "printk.h" + +struct keyboard_inputbuffer * p_mouse = NULL; +static int mouse_count = 0; +struct mouse_packet mouse; + +/* + +*/ + +void mouse_handler(unsigned long nr, unsigned long parameter, struct pt_regs * regs) +{ + unsigned char x; + x = io_in8(PORT_KB_DATA); + color_printk(GREEN,WHITE,"(M:%02x)",x); + + if(p_mouse->p_head == p_mouse->buf + KB_BUF_SIZE) + p_mouse->p_head = p_mouse->buf; + + *p_mouse->p_head = x; + p_mouse->count++; + p_mouse->p_head ++; +} + +/* + +*/ + +unsigned char get_mousecode() +{ + unsigned char ret = 0; + + if(p_mouse->count == 0) + while(!p_mouse->count) + nop(); + + if(p_mouse->p_tail == p_mouse->buf + KB_BUF_SIZE) + p_mouse->p_tail = p_mouse->buf; + + ret = *p_mouse->p_tail; + p_mouse->count--; + p_mouse->p_tail++; + + return ret; +} + +/* + +*/ + +void analysis_mousecode() +{ + unsigned char x = get_mousecode(); + + switch(mouse_count) + { + case 0: + mouse_count++; + break; + + case 1: + mouse.Byte0 = x; + mouse_count++; + break; + + case 2: + mouse.Byte1 = (char)x; + mouse_count++; + break; + + case 3: + mouse.Byte2 = (char)x; + mouse_count = 1; + color_printk(RED,GREEN,"(M:%02x,X:%3d,Y:%3d)\n",mouse.Byte0,mouse.Byte1,mouse.Byte2); + break; + + default: + break; + } +} + +hw_int_controller mouse_int_controller = +{ + .enable = IOAPIC_enable, + .disable = IOAPIC_disable, + .install = IOAPIC_install, + .uninstall = IOAPIC_uninstall, + .ack = IOAPIC_edge_ack, +}; + + +/* + +*/ + +void mouse_init() +{ + struct IO_APIC_RET_entry entry; + unsigned long i,j; + + p_mouse = (struct keyboard_inputbuffer *)kmalloc(sizeof(struct keyboard_inputbuffer),0); + + p_mouse->p_head = p_mouse->buf; + p_mouse->p_tail = p_mouse->buf; + p_mouse->count = 0; + memset(p_mouse->buf,0,KB_BUF_SIZE); + + entry.vector = 0x2c; + entry.deliver_mode = APIC_ICR_IOAPIC_Fixed ; + entry.dest_mode = ICR_IOAPIC_DELV_PHYSICAL; + entry.deliver_status = APIC_ICR_IOAPIC_Idle; + entry.polarity = APIC_IOAPIC_POLARITY_HIGH; + entry.irr = APIC_IOAPIC_IRR_RESET; + entry.trigger = APIC_ICR_IOAPIC_Edge; + entry.mask = APIC_ICR_IOAPIC_Masked; + entry.reserved = 0; + + entry.destination.physical.reserved1 = 0; + entry.destination.physical.phy_dest = 0; + entry.destination.physical.reserved2 = 0; + + mouse_count = 0; + + register_irq(0x2c, &entry , &mouse_handler, (unsigned long)p_mouse, &mouse_int_controller, "ps/2 mouse"); + + wait_KB_write(); + io_out8(PORT_KB_CMD,KBCMD_EN_MOUSE_INTFACE); + + for(i = 0;i<1000;i++) + for(j = 0;j<1000;j++) + nop(); + + wait_KB_write(); + io_out8(PORT_KB_CMD,KBCMD_SENDTO_MOUSE); + wait_KB_write(); + io_out8(PORT_KB_DATA,MOUSE_ENABLE); + + for(i = 0;i<1000;i++) + for(j = 0;j<1000;j++) + nop(); + + wait_KB_write(); + io_out8(PORT_KB_CMD,KBCMD_WRITE_CMD); + wait_KB_write(); + io_out8(PORT_KB_DATA,KB_INIT_MODE); +} + +/* + +*/ + +void mouse_exit() +{ + unregister_irq(0x2c); + kfree((unsigned long *)p_mouse); +} diff --git a/kernel/mouse.h b/kernel/mouse.h new file mode 100644 index 0000000000000000000000000000000000000000..377449f99d6508decc28f1daf208a8947c938dd6 --- /dev/null +++ b/kernel/mouse.h @@ -0,0 +1,42 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ +#ifndef __MOUSE_H__ + +#define __MOUSE_H__ + +extern struct keyboard_inputbuffer * p_mouse; + +#define KBCMD_SENDTO_MOUSE 0xd4 +#define MOUSE_ENABLE 0xf4 + +#define KBCMD_EN_MOUSE_INTFACE 0xa8 + +struct mouse_packet +{ + unsigned char Byte0; //7:Y overflow,6:X overflow,5:Y sign bit,4:X sign bit,3:Always,2:Middle Btn,1:Right Btn,0:Left Btn + char Byte1; //X movement + char Byte2; //Y movement +}; + +extern struct mouse_packet mouse; + +/* + +*/ + +void mouse_init(); +void mouse_exit(); + +/* + +*/ + +void analysis_mousecode(); + +#endif diff --git a/kernel/preempt.h b/kernel/preempt.h new file mode 100644 index 0000000000000000000000000000000000000000..5d28d587bb517b0cc091c70e72bd5b8d4a754666 --- /dev/null +++ b/kernel/preempt.h @@ -0,0 +1,32 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __PREEMPT_H__ + +#define __PREEMPT_H__ + +#include "task.h" + +/* + +*/ + +#define preempt_enable() \ +do \ +{ \ + current->preempt_count--; \ +}while(0) + +#define preempt_disable() \ +do \ +{ \ + current->preempt_count++; \ +}while(0) + +#endif diff --git a/kernel/printk.c b/kernel/printk.c index 4ac07f8df3105886513644fe3b2e482aa03f9c0f..9afc44bfbbac822640a1d39a6cbb98a0c9833aad 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -9,25 +9,60 @@ #include #include "printk.h" -#include "lib.h" -#include "linkage.h" +#include "memory.h" +#include "spinlock.h" static char buf[4096]={0}; -struct position Pos= +struct position Pos; + +#ifdef UEFI +#include "UEFI_boot_param_info.h" +#define FB_PHY_ADDR (((volatile struct KERNEL_BOOT_PARAMETER_INFORMATION *)0xffff800000060000)->Graphics_Info.FrameBufferBase) +#else +#define FB_PHY_ADDR (0xe0000000) +#endif + +/* + +*/ + +void frame_buffer_init() { - .XResolution=1024, - .YResolution=768, + ////re init frame buffer; + unsigned long i; + unsigned long * tmp; + unsigned long * tmp1; + unsigned int * FB_addr = (unsigned int *)Phy_To_Virt(FB_PHY_ADDR); + + tmp = Phy_To_Virt((unsigned long *)((unsigned long)Get_gdt() & (~ 0xfffUL)) + (((unsigned long)FB_addr >> PAGE_GDT_SHIFT) & 0x1ff)); + if (*tmp == 0) + { + unsigned long * virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_mpl4t(tmp,mk_mpl4t(Virt_To_Phy(virtual),PAGE_KERNEL_GDT)); + } - .XPosition=0, - .YPosition=0, + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + (((unsigned long)FB_addr >> PAGE_1G_SHIFT) & 0x1ff)); + if(*tmp == 0) + { + unsigned long * virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_pdpt(tmp,mk_pdpt(Virt_To_Phy(virtual),PAGE_KERNEL_Dir)); + } + + for(i = 0;i < Pos.FB_length;i += PAGE_2M_SIZE) + { + tmp1 = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + (((unsigned long)((unsigned long)FB_addr + i) >> PAGE_2M_SHIFT) & 0x1ff)); + + unsigned long phy = FB_PHY_ADDR + i; + set_pdt(tmp1,mk_pdt(phy,PAGE_KERNEL_Page | PAGE_PWT | PAGE_PCD)); + } - .XCharSize=8, - .YCharSize=16, + Pos.FB_addr = (unsigned int *)Phy_To_Virt(FB_PHY_ADDR); - .FB_addr=(int *)0xffff800003000000, - .FB_length=0x300000, -}; + flush_tlb(); +} /* @@ -58,7 +93,6 @@ void putchar(unsigned int * fb,int Xsize,int x,int y,unsigned int FRcolor,unsign } } - /* */ @@ -280,9 +314,9 @@ int vsprintf(char * buf,const char *fmt, va_list args) case 'u': if(qualifier == 'l') - str = number(str,va_arg(args,unsigned long),10,field_width,precision,flags); + str = number(str,va_arg(args,long),10,field_width,precision,flags); else - str = number(str,va_arg(args,unsigned int),10,field_width,precision,flags); + str = number(str,va_arg(args,int),10,field_width,precision,flags); break; case 'n': @@ -328,11 +362,13 @@ int color_printk(unsigned int FRcolor,unsigned int BKcolor,const char * fmt,...) int i = 0; int count = 0; int line = 0; + unsigned long flags = 0; va_list args; - va_start(args, fmt); - i = vsprintf(buf,fmt, args); + spin_lock_irqsave(&Pos.printk_lock,flags); + va_start(args, fmt); + i = vsprintf(buf,fmt, args); va_end(args); for(count = 0;count < i || line;count++) @@ -387,5 +423,8 @@ Label_tab: } } + + spin_unlock_irqrestore(&Pos.printk_lock,flags); + return i; } diff --git a/kernel/printk.h b/kernel/printk.h index e152a0c83e1a5b00b62892fb81f7ac60c6349fd3..b9486e01b8b39d92459bbd70017cfdcde363a001 100644 --- a/kernel/printk.h +++ b/kernel/printk.h @@ -8,11 +8,13 @@ ***************************************************/ #ifndef __PRINTK_H__ + #define __PRINTK_H__ #include #include "font.h" #include "linkage.h" +#include "spinlock.h" #define ZEROPAD 1 /* pad with zero */ #define SIGN 2 /* unsigned/signed long */ @@ -53,6 +55,8 @@ struct position unsigned int * FB_addr; unsigned long FB_length; + + spinlock_T printk_lock; }; extern struct position Pos; @@ -61,6 +65,12 @@ extern struct position Pos; */ +void frame_buffer_init(); + +/* + +*/ + void putchar(unsigned int * fb,int Xsize,int x,int y,unsigned int FRcolor,unsigned int BKcolor,unsigned char font); /* diff --git a/kernel/sched.h b/kernel/sched.h new file mode 100644 index 0000000000000000000000000000000000000000..928b095c8d3b35442ff3b488219dca08bc7bf221 --- /dev/null +++ b/kernel/sched.h @@ -0,0 +1,24 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __SCHED_H__ + +#define __SCHED_H__ + +/* + * cloning flags: + */ + + +#define CLONE_VM (1 << 0) /* shared Virtual Memory between processes */ +#define CLONE_FS (1 << 1) /* shared fs info between processes */ +#define CLONE_SIGNAL (1 << 2) /* shared signal between processes */ + + +#endif diff --git a/kernel/schedule.c b/kernel/schedule.c new file mode 100644 index 0000000000000000000000000000000000000000..106cf8d2ebc2b5c5bb853d26b5cd07f47a99b1d5 --- /dev/null +++ b/kernel/schedule.c @@ -0,0 +1,127 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "schedule.h" +#include "task.h" +#include "lib.h" +#include "printk.h" +#include "timer.h" +#include "SMP.h" + +struct schedule task_schedule[NR_CPUS]; + +struct task_struct *get_next_task() +{ + struct task_struct * tsk = NULL; + + if(list_is_empty(&task_schedule[SMP_cpu_id()].task_queue.list)) + { + return init_task[SMP_cpu_id()]; + } + + tsk = container_of(list_next(&task_schedule[SMP_cpu_id()].task_queue.list),struct task_struct,list); + list_del(&tsk->list); + + task_schedule[SMP_cpu_id()].running_task_count -= 1; + + return tsk; +} + +void insert_task_queue(struct task_struct *tsk) +{ + struct task_struct *tmp = NULL; + + if(tsk == init_task[SMP_cpu_id()]) + return ; + + tmp = container_of(list_next(&task_schedule[SMP_cpu_id()].task_queue.list),struct task_struct,list); + + if(list_is_empty(&task_schedule[SMP_cpu_id()].task_queue.list)) + { + } + else + { + while(tmp->vrun_time < tsk->vrun_time) + tmp = container_of(list_next(&tmp->list),struct task_struct,list); + } + + list_add_to_before(&tmp->list,&tsk->list); + task_schedule[SMP_cpu_id()].running_task_count += 1; +} + +void schedule() +{ + struct task_struct *tsk = NULL; + long cpu_id = SMP_cpu_id(); + + cli(); + + current->flags &= ~NEED_SCHEDULE; + tsk = get_next_task(); +// color_printk(YELLOW,BLACK,"RFLAGS:%#018lx\n",get_rflags()); +// color_printk(YELLOW,BLACK,"#schedule:%ld,pid:%ld(%ld)=>>pid:%ld(%ld)#\n",jiffies,current->pid,current->vrun_time,tsk->pid,tsk->vrun_time); + + if(current->vrun_time >= tsk->vrun_time || current->state != TASK_RUNNING) + { + if(current->state == TASK_RUNNING) + insert_task_queue(current); + + if(!task_schedule[cpu_id].CPU_exec_task_jiffies) + switch(tsk->priority) + { + case 0: + case 1: + task_schedule[cpu_id].CPU_exec_task_jiffies = 4/task_schedule[cpu_id].running_task_count; + break; + case 2: + default: + task_schedule[cpu_id].CPU_exec_task_jiffies = 4/task_schedule[cpu_id].running_task_count*3; + break; + } + + switch_mm(current,tsk); + switch_to(current,tsk); + } + else + { + insert_task_queue(tsk); + + if(!task_schedule[cpu_id].CPU_exec_task_jiffies) + switch(tsk->priority) + { + case 0: + case 1: + task_schedule[cpu_id].CPU_exec_task_jiffies = 4/task_schedule[cpu_id].running_task_count; + break; + case 2: + default: + task_schedule[cpu_id].CPU_exec_task_jiffies = 4/task_schedule[cpu_id].running_task_count*3; + break; + } + } + + sti(); +} + +void schedule_init() +{ + int i = 0; + memset(&task_schedule,0,sizeof(struct schedule) * NR_CPUS); + + for(i = 0;icounter,count); + wait_queue_init(&semaphore->wait,NULL); +} + +void __up(semaphore_T * semaphore) +{ + wait_queue_T * wait = container_of(list_next(&semaphore->wait.wait_list),wait_queue_T,wait_list); + + list_del(&wait->wait_list); + wait->tsk->state = TASK_RUNNING; + insert_task_queue(wait->tsk); + current->flags |= NEED_SCHEDULE; +} + +void semaphore_up(semaphore_T * semaphore) +{ + if(list_is_empty(&semaphore->wait.wait_list)) + atomic_inc(&semaphore->counter); + else + __up(semaphore); +} + +void __down(semaphore_T * semaphore) +{ + wait_queue_T wait; + wait_queue_init(&wait,current); + current->state = TASK_UNINTERRUPTIBLE; + list_add_to_before(&semaphore->wait.wait_list,&wait.wait_list); + + schedule(); +} + +void semaphore_down(semaphore_T * semaphore) +{ + if(atomic_read(&semaphore->counter) > 0) + atomic_dec(&semaphore->counter); + else + __down(semaphore); +} + diff --git a/kernel/semaphore.h b/kernel/semaphore.h new file mode 100644 index 0000000000000000000000000000000000000000..18492ac15fbd0207d4739036ab11480d02d27929 --- /dev/null +++ b/kernel/semaphore.h @@ -0,0 +1,32 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __SEMAPHORE_H__ + +#define __SEMAPHORE_H__ + +#include "atomic.h" +#include "lib.h" +#include "task.h" +#include "schedule.h" +#include "waitqueue.h" + +typedef struct +{ + atomic_T counter; + wait_queue_T wait; +} semaphore_T; + +void semaphore_init(semaphore_T * semaphore,unsigned long count); + +void semaphore_up(semaphore_T * semaphore); + +void semaphore_down(semaphore_T * semaphore); + +#endif diff --git a/kernel/serial.c b/kernel/serial.c new file mode 100644 index 0000000000000000000000000000000000000000..72785b6c3655e5809b1ffea4e6318e0be5266d4d --- /dev/null +++ b/kernel/serial.c @@ -0,0 +1,232 @@ +/************************************************************************* + > File Name: serial.c + > Author: + > Mail: + > Created Time: 2019å¹´06月11æ—¥ 星期二 00æ—¶47分14ç§’ + ************************************************************************/ + +#include "serial.h" +#include "printk.h" +#include "io.h" +#include "lib.h" +#include "APIC.h" +#include "memory.h" + +#define BASE_BAUD ( 1843200 / 16 ) +#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF) + +/********** declaration ********/ +static void change_speed(unsigned int line); +static void rs_interrupt_init(); + +/************* define *************/ +struct serial_des rs_table[] = { + /* UART CLK PORT IRQ FLAGS */ + { BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS, 0, 0}, /* ttyS0 */ +}; + +hw_int_controller rs_int_controller = +{ + .enable = IOAPIC_enable, + .disable = IOAPIC_disable, + .install = IOAPIC_install, + .uninstall = IOAPIC_uninstall, + .ack = IOAPIC_edge_ack, +}; + +#define NR_PORTS (sizeof(rs_table)/sizeof(struct serial_des)) + +/* + * This is used to figure out the divsor speeds and the timeouts + */ +static int baud_table[] = { + 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, + 9600, 19200, 38400, 57600, 115200, 0 }; + +static inline unsigned int serial_in(struct serial_des *info, int offset) +{ + return inb(info->port + offset); +} + +static inline unsigned int serial_inp(struct serial_des *info, int offset) +{ + return inb_p(info->port + offset); +} + +static inline unsigned int serial_out(struct serial_des *info, int offset, int val) +{ + outb(val, info->port+offset); +} + +static inline unsigned int serial_outp(struct serial_des *info, int offset, int val) +{ + outb_p(val, info->port+offset); +} + +/* init serial */ +void init_serial(struct serial_des* info, int get_irq) +{ + /* + * Clear the interrupt registers. + */ + (void)serial_inp(info, UART_LSR); + (void)serial_inp(info, UART_RX); + (void)serial_inp(info, UART_IIR); + (void)serial_inp(info, UART_MSR); + + /* + * Now, initialize the UART + */ + serial_outp(info, UART_LCR, UART_LCR_WLEN8); /* reset DLAB */ + serial_outp(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2); + + /* + * + */ + //serial_outp(info, UART_IER, 0); /* disable all intrs */ + serial_outp(info, UART_IER, UART_IER_RDI); /* data ready interrupt */ + rs_interrupt_init(); + + /* + * Set up parity check flag, no parity + */ + int read_status_mask = (UART_LSR_OE | UART_LSR_BI | UART_LSR_FE); + + /* + * and set the speed of the serial port + */ + change_speed(info->line); +} + +/* loop recieve chars */ +void loop_receive_chars(struct serial_des *info) +{ + int ch = -1, status = -1; + while(1) { + status = serial_inp(info, UART_LSR); + if (status & UART_LSR_DR){ + do { + ch = serial_inp(info, UART_RX); + color_printk(GREEN, BLACK, "%c", ch); + }while((status = serial_inp(info, UART_LSR)) & UART_LSR_DR); + } + } +} + +/* interrupt */ +static void receive_chars(struct serial_des *info, int *status) +{ + int ch = -1; + do { + ch = serial_inp(info, UART_RX); + color_printk(GREEN, BLACK, "%c", ch); + }while((*status = serial_inp(info, UART_LSR)) & UART_LSR_DR); + +} + +/* transmit chars */ + + +/* interrupt routine */ +void rs_handler(unsigned long nr, unsigned long parameter, struct pt_regs * regs) +{ + int ch = -1, status = -1; + struct serial_des *info = &rs_table[0]; + + int done, done_work, pass_number, recheck_count; + + done = 1; + done_work = 0; + pass_number = 0; + //color_printk(GREEN, BLACK, "in interrupt!\n"); + + while(info) { + if(!(serial_inp(info, UART_IIR) & UART_IIR_NO_INT)) { + done = 0; + status = serial_inp(info, UART_LSR); + if (status & UART_LSR_DR) { + receive_chars(info, &status); + done_work++; + } + #if 0 + recheck_write: + if (status & UART_LSR_THRE) { + wake_up_interruptible(&info->xmit_wait); + if (!info->tty->stopped && + !info->tty->hw_stopped) + transmit_chars(info, &done_work); + } + if (check_modem_status(info) && + (recheck_count++ <= 64)) + goto recheck_write; +#ifdef SERIAL_DEBUG_INTR + if (recheck_count > 16) + printk("recheck_count = %d\n", recheck_count); +#endif + } + #endif + } + info = NULL; + if (!info && !done) { + // info = IRQ_ports[irq]; + done = 1; + if (pass_number++ > 64) + break; /* Prevent infinite loops */ + } + } + +} + +/* + * This routine is called to set the UART divisor registers to match + * the specified baud rate for a serial port. + */ +static void change_speed(unsigned int line) +{ + struct serial_des * info; + unsigned short port; + int quot = 1; /* 115200 / 115200 = 1 */ + unsigned char cval,fcr; + int i; + + if (line >= NR_PORTS) + return; + info = rs_table + line; + + /* byte size and parity */ + cval = UART_LCR_WLEN8 | ~(UART_LCR_STOP) | ~(UART_LCR_PARITY); /* 8N1 */ + cval = 0x03; + fcr = 0; + + /* 115200, BR = 1843200 / (16*(PSD+1)*DL) , PSD reset value=0, set DL=1*/ + serial_outp(info, UART_LCR, cval | UART_LCR_DLAB); /* set DLAB */ + serial_outp(info, UART_DLL, quot & 0xff); /* LS of divisor */ + serial_outp(info, UART_DLM, quot >> 8); /* MS of divisor */ + + serial_outp(info, UART_LCR, cval); /* reset DLAB */ + serial_outp(info, UART_FCR, fcr); /* set fcr */ +} + +/* COM1 -> IRQ4, INT 36(0x24) */ +static void rs_interrupt_init() +{ + struct IO_APIC_RET_entry entry; + unsigned long i,j; + + entry.vector = 0x24; + entry.deliver_mode = APIC_ICR_IOAPIC_Fixed ; + entry.dest_mode = ICR_IOAPIC_DELV_PHYSICAL; + entry.deliver_status = APIC_ICR_IOAPIC_Idle; + entry.polarity = APIC_IOAPIC_POLARITY_HIGH; + entry.irr = APIC_IOAPIC_IRR_RESET; + entry.trigger = APIC_ICR_IOAPIC_Edge; + entry.mask = APIC_ICR_IOAPIC_Masked; + entry.reserved = 0; + + entry.destination.physical.reserved1 = 0; + entry.destination.physical.phy_dest = 0; + entry.destination.physical.reserved2 = 0; + + + register_irq(0x24, &entry , &rs_handler, NULL, &rs_int_controller, "UART"); +} \ No newline at end of file diff --git a/kernel/serial.h b/kernel/serial.h new file mode 100644 index 0000000000000000000000000000000000000000..c995d38a802bb6e1d12e06d047bc4838a6c66c0f --- /dev/null +++ b/kernel/serial.h @@ -0,0 +1,143 @@ +/************************************************************************* + > File Name: serial.h + > Author: + > Mail: + > Created Time: 2019å¹´06月11æ—¥ 星期二 00æ—¶46分22ç§’ + ************************************************************************/ + +#ifndef _SERIAL_H +#define _SERIAL_H + +struct serial_des { + int baud_base; + int port; + int irq; + int flags; + int type; + int line; +}; + +/* Internal flags used only by kernel/chr_drv/serial.c */ +#define ASYNC_INITIALIZED 0x80000000 /* Serial port was initialized */ +#define ASYNC_CALLOUT_ACTIVE 0x40000000 /* Call out device is active */ +#define ASYNC_NORMAL_ACTIVE 0x20000000 /* Normal device is active */ +#define ASYNC_BOOT_AUTOCONF 0x10000000 /* Autoconfigure port on bootup */ +#define ASYNC_CLOSING 0x08000000 /* Serial port is closing */ + +/* + * Events are used to schedule things to happen at timer-interrupt + * time, instead of at rs interrupt time. + */ +#define RS_EVENT_READ_PROCESS 0 +#define RS_EVENT_WRITE_WAKEUP 1 +#define RS_EVENT_HANGUP 2 +#define RS_EVENT_BREAK 3 +#define RS_EVENT_OPEN_WAKEUP 4 + +/* + * These are the UART port assignments, expressed as offsets from the base + * register. These assignments should hold for any serial port based on + * a 8250, 16450, or 16550(A). + */ +#define UART_RX 0 /* In: Receive buffer (DLAB=0) */ +#define UART_TX 0 /* Out: Transmit buffer (DLAB=0) */ +#define UART_DLL 0 /* Out: Devisor Latch Low (DLAB=1) */ +#define UART_DLM 1 /* Out: Devisor Latch High (DLAB=1) */ +#define UART_IER 1 /* Out: Interrupt Enable Register */ +#define UART_IIR 2 /* In: Interrupt ID Register */ +#define UART_FCR 2 /* Out: FIFO Control Register */ +#define UART_LCR 3 /* Out: Line Control Register */ +#define UART_MCR 4 /* Out: Modem Control Register */ +#define UART_LSR 5 /* In: Line Status Register */ +#define UART_MSR 6 /* In: Modem Status Register */ +#define UART_SCR 7 /* I/O: Scratch Register */ + +/* + * These are the definitions for the FIFO Control Register + */ +#define UART_FCR_ENABLE_FIFO 0x01 /* Enable the FIFO */ +#define UART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */ +#define UART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */ +#define UART_FCR_DMA_SELECT 0x08 /* For DMA applications */ +#define UART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */ +#define UART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */ +#define UART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */ +#define UART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */ +#define UART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */ + +/* + * These are the definitions for the Line Control Register + * + * Note: if the word length is 5 bits (UART_LCR_WLEN5), then setting + * UART_LCR_STOP will select 1.5 stop bits, not 2 stop bits. + */ +#define UART_LCR_DLAB 0x80 /* Devisor latch access bit */ +#define UART_LCR_SBC 0x40 /* Set break control */ +#define UART_LCR_SPAR 0x20 /* Stick parity (?) */ +#define UART_LCR_EPAR 0x10 /* Even paraity select */ +#define UART_LCR_PARITY 0x08 /* Parity Enable */ +#define UART_LCR_STOP 0x04 /* Stop bits: 0=1 stop bit, 1= 2 stop bits */ +#define UART_LCR_WLEN5 0x00 /* Wordlength: 5 bits */ +#define UART_LCR_WLEN6 0x01 /* Wordlength: 6 bits */ +#define UART_LCR_WLEN7 0x02 /* Wordlength: 7 bits */ +#define UART_LCR_WLEN8 0x03 /* Wordlength: 8 bits */ + +/* + * These are the definitions for the Line Status Register + */ +#define UART_LSR_TEMT 0x40 /* Transmitter empty */ +#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */ +#define UART_LSR_BI 0x10 /* Break interrupt indicator */ +#define UART_LSR_FE 0x08 /* Frame error indicator */ +#define UART_LSR_PE 0x04 /* Parity error indicator */ +#define UART_LSR_OE 0x02 /* Overrun error indicator */ +#define UART_LSR_DR 0x01 /* Receiver data ready */ + +/* + * These are the definitions for the Interrupt Indentification Register + */ +#define UART_IIR_NO_INT 0x01 /* No interrupts pending */ +#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */ + +#define UART_IIR_MSI 0x00 /* Modem status interrupt */ +#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */ +#define UART_IIR_RDI 0x04 /* Receiver data interrupt */ +#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */ + +/* + * These are the definitions for the Interrupt Enable Register + */ +#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */ +#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */ +#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */ +#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */ + +/* + * These are the definitions for the Modem Control Register + */ +#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */ +#define UART_MCR_OUT2 0x08 /* Out2 complement */ +#define UART_MCR_OUT1 0x04 /* Out1 complement */ +#define UART_MCR_RTS 0x02 /* RTS complement */ +#define UART_MCR_DTR 0x01 /* DTR complement */ + +/* + * These are the definitions for the Modem Status Register + */ +#define UART_MSR_DCD 0x80 /* Data Carrier Detect */ +#define UART_MSR_RI 0x40 /* Ring Indicator */ +#define UART_MSR_DSR 0x20 /* Data Set Ready */ +#define UART_MSR_CTS 0x10 /* Clear to Send */ +#define UART_MSR_DDCD 0x08 /* Delta DCD */ +#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */ +#define UART_MSR_DDSR 0x02 /* Delta DSR */ +#define UART_MSR_DCTS 0x01 /* Delta CTS */ +#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */ + + +/* init serial */ +void init_serial(struct serial_des* info, int get_irq); + +/* recieve chars */ +void loop_receive_chars(struct serial_des *info); +#endif diff --git a/kernel/softirq.c b/kernel/softirq.c new file mode 100644 index 0000000000000000000000000000000000000000..7fa93992272724aaa308a7979c39d66036432545 --- /dev/null +++ b/kernel/softirq.c @@ -0,0 +1,57 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "softirq.h" +#include "lib.h" + +unsigned long softirq_status = 0; +struct softirq softirq_vector[64] = {0}; + +void set_softirq_status(unsigned long status) +{ + softirq_status |= status; +} + +unsigned long get_softirq_status() +{ + return softirq_status; +} + +void register_softirq(int nr,void (*action)(void * data),void * data) +{ + softirq_vector[nr].action = action; + softirq_vector[nr].data = data; +} + +void unregister_softirq(int nr) +{ + softirq_vector[nr].action = NULL; + softirq_vector[nr].data = NULL; +} + +void do_softirq() +{ + int i; + sti(); + for(i = 0;i < 64 && softirq_status;i++) + { + if(softirq_status & (1 << i)) + { + softirq_vector[i].action(softirq_vector[i].data); + softirq_status &= ~(1 << i); + } + } + cli(); +} + +void softirq_init() +{ + softirq_status = 0; + memset(softirq_vector,0,sizeof(struct softirq) * 64); +} diff --git a/kernel/softirq.h b/kernel/softirq.h new file mode 100644 index 0000000000000000000000000000000000000000..f157b64287ddc01b4c78d534a41c634492af1cce --- /dev/null +++ b/kernel/softirq.h @@ -0,0 +1,35 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __SOFTIRQ_H__ + +#define __SOFTIRQ_H__ + +#define TIMER_SIRQ (1 << 0) + +extern unsigned long softirq_status; + +struct softirq +{ + void (*action)(void * data); + void * data; +}; + +extern struct softirq softirq_vector[64]; + + +void register_softirq(int nr,void (*action)(void * data),void * data); +void unregister_softirq(int nr); + +void set_softirq_status(unsigned long status); +unsigned long get_softirq_status(); + +void softirq_init(); + +#endif diff --git a/kernel/spinlock.h b/kernel/spinlock.h new file mode 100644 index 0000000000000000000000000000000000000000..23db7de7018f281c48290506566d4756b357f87b --- /dev/null +++ b/kernel/spinlock.h @@ -0,0 +1,118 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __SPINLOCK_H__ + +#define __SPINLOCK_H__ + +#include "preempt.h" +#include "lib.h" + +/* + +*/ + +typedef struct +{ + __volatile__ unsigned long lock; //1:unlock,0:lock +}spinlock_T; + +/* + +*/ + +inline void spin_init(spinlock_T * lock) +{ + lock->lock = 1; +} + +/* + +*/ + +inline void spin_lock(spinlock_T * lock) +{ + preempt_disable(); + __asm__ __volatile__ ( "1: \n\t" + "lock decq %0 \n\t" + "jns 3f \n\t" + "2: \n\t" + "pause \n\t" + "cmpq $0, %0 \n\t" + "jle 2b \n\t" + "jmp 1b \n\t" + "3: \n\t" + :"=m"(lock->lock) + : + :"memory" + ); +} + +/* + +*/ + +inline void spin_unlock(spinlock_T * lock) +{ + __asm__ __volatile__ ( "movq $1, %0 \n\t" + :"=m"(lock->lock) + : + :"memory" + ); + preempt_enable(); +} + +inline long spin_trylock(spinlock_T * lock) +{ + unsigned long tmp_value = 0; + preempt_disable(); + __asm__ __volatile__ ( "xchgq %0, %1 \n\t" + :"=q"(tmp_value),"=m"(lock->lock) + :"0"(0) + :"memory" + ); + if(!tmp_value) + preempt_enable(); + return tmp_value; +} + +#define local_irq_save(x) __asm__ __volatile__("pushfq ; popq %0 ; cli":"=g"(x)::"memory") +#define local_irq_restore(x) __asm__ __volatile__("pushq %0 ; popfq"::"g"(x):"memory") +#define local_irq_disable() cli(); +#define local_irq_enable() sti(); + +#define spin_lock_irqsave(lock,flags) \ +do \ +{ \ + local_irq_save(flags); \ + spin_lock(lock); \ +}while(0) + +#define spin_unlock_irqrestore(lock,flags) \ +do \ +{ \ + spin_unlock(lock); \ + local_irq_restore(flags); \ +}while(0) + +#define spin_lock_irq(lock) \ +do \ +{ \ + local_irq_disable(); \ + spin_lock(lock); \ +}while(0) + +#define spin_unlock_irq(lock) \ +do \ +{ \ + spin_unlock(lock); \ + local_irq_enable(); \ +}while(0) + +#endif diff --git a/kernel/stdio.h b/kernel/stdio.h new file mode 100644 index 0000000000000000000000000000000000000000..153bf067f3f4bd403348a69cb9a75dfb1a46b712 --- /dev/null +++ b/kernel/stdio.h @@ -0,0 +1,21 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __STDIO_H__ + +#define __STDIO_H__ + +#define SEEK_SET 0 /* Seek relative to start-of-file */ +#define SEEK_CUR 1 /* Seek relative to current position */ +#define SEEK_END 2 /* Seek relative to end-of-file */ + +#define SEEK_MAX 3 + + +#endif diff --git a/kernel/sys.c b/kernel/sys.c index a480ec691d0b7493673b219d3a7393c85637ac99..52a3c2136221fcd522e9ca7b3544872234131350 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -10,6 +10,19 @@ #include "errno.h" #include "printk.h" +#include "lib.h" +#include "VFS.h" +#include "fcntl.h" +#include "memory.h" +#include "fat32.h" +#include "stdio.h" +#include "fcntl.h" +#include "ptrace.h" +#include "task.h" +#include "sched.h" +#include "memory.h" +#include "keyboard.h" +#include "sys.h" /* normal @@ -34,33 +47,349 @@ unsigned long no_system_call(void) return -ENOSYS; } -/* -__asm__ ( -".global puts \n\t" -".type puts, @function \n\t" -"puts: \n\t" -"pushq %r10 \n\t" -"pushq %r11 \n\t" -"movq $__NR_puts , %rax \n\t" -"leaq sysexit_return_address(%rip), %r10 \n\t" -"movq %rsp, %r11 \n\t" -"sysenter \n\t" -"sysexit_return_address: \n\t" -"xchgq %rdx, %r10 \n\t" -"xchgq %rcx, %r11 \n\t" -"popq %r11 \n\t" -"popq %r10 \n\t" -); +unsigned long sys_putstring(char *string) +{ + color_printk(ORANGE,WHITE,string); + return 0; +} + +unsigned long sys_open(char *filename,int flags) +{ + char * path = NULL; + long pathlen = 0; + long error = 0; + struct dir_entry * dentry = NULL; + struct file * filp = NULL; + struct file ** f = NULL; + int fd = -1; + int i; + +// color_printk(GREEN,BLACK,"sys_open\n"); + path = (char *)kmalloc(PAGE_4K_SIZE,0); + if(path == NULL) + return -ENOMEM; + memset(path,0,PAGE_4K_SIZE); + pathlen = strnlen_user(filename,PAGE_4K_SIZE); + if(pathlen <= 0) + { + kfree(path); + return -EFAULT; + } + else if(pathlen >= PAGE_4K_SIZE) + { + kfree(path); + return -ENAMETOOLONG; + } + strncpy_from_user(filename,path,pathlen); + + dentry = path_walk(path,0); + kfree(path); + + if(dentry == NULL) + return -ENOENT; + + if((flags & O_DIRECTORY) && (dentry->dir_inode->attribute != FS_ATTR_DIR)) + return -ENOTDIR; + if(!(flags & O_DIRECTORY) && (dentry->dir_inode->attribute == FS_ATTR_DIR)) + return -EISDIR; + + filp = (struct file *)kmalloc(sizeof(struct file),0); + memset(filp,0,sizeof(struct file)); + filp->dentry = dentry; + filp->mode = flags; + + if(dentry->dir_inode->attribute & FS_ATTR_DEVICE) + filp->f_ops = &keyboard_fops; ////// find device file operation function + else + filp->f_ops = dentry->dir_inode->f_ops; + if(filp->f_ops && filp->f_ops->open) + error = filp->f_ops->open(dentry->dir_inode,filp); + if(error != 1) + { + kfree(filp); + return -EFAULT; + } + + if(filp->mode & O_TRUNC) + { + filp->dentry->dir_inode->file_size = 0; + } + if(filp->mode & O_APPEND) + { + filp->position = filp->dentry->dir_inode->file_size; + } + + f = current->file_struct; + for(i = 0;i < TASK_FILE_MAX;i++) + if(f[i] == NULL) + { + fd = i; + break; + } + if(i == TASK_FILE_MAX) + { + kfree(filp); + //// reclaim struct index_node & struct dir_entry + return -EMFILE; + } + f[fd] = filp; + + return fd; +} + +unsigned long sys_close(int fd) +{ + struct file * filp = NULL; + +// color_printk(GREEN,BLACK,"sys_close:%d\n",fd); + if(fd < 0 || fd >= TASK_FILE_MAX) + return -EBADF; + + filp = current->file_struct[fd]; + if(filp->f_ops && filp->f_ops->close) + filp->f_ops->close(filp->dentry->dir_inode,filp); + + kfree(filp); + current->file_struct[fd] = NULL; + + return 0; +} + +unsigned long sys_read(int fd,void * buf,long count) +{ + struct file * filp = NULL; + unsigned long ret = 0; + +// color_printk(GREEN,BLACK,"sys_read:%d\n",fd); + if(fd < 0 || fd >= TASK_FILE_MAX) + return -EBADF; + if(count < 0) + return -EINVAL; + + filp = current->file_struct[fd]; + if(filp->f_ops && filp->f_ops->read) + ret = filp->f_ops->read(filp,buf,count,&filp->position); + return ret; +} + +unsigned long sys_write(int fd,void * buf,long count) +{ + struct file * filp = NULL; + unsigned long ret = 0; + +// color_printk(GREEN,BLACK,"sys_write:%d\n",fd); + if(fd < 0 || fd >= TASK_FILE_MAX) + return -EBADF; + if(count < 0) + return -EINVAL; + + filp = current->file_struct[fd]; + if(filp->f_ops && filp->f_ops->write) + ret = filp->f_ops->write(filp,buf,count,&filp->position); + return ret; +} + + +unsigned long sys_lseek(int filds,long offset,int whence) +{ + struct file * filp = NULL; + unsigned long ret = 0; + +// color_printk(GREEN,BLACK,"sys_lseek:%d\n",filds); + if(filds < 0 || filds >= TASK_FILE_MAX) + return -EBADF; + if(whence < 0 || whence >= SEEK_MAX) + return -EINVAL; + + filp = current->file_struct[filds]; + if(filp->f_ops && filp->f_ops->lseek) + ret = filp->f_ops->lseek(filp,offset,whence); + return ret; +} + +unsigned long sys_fork() +{ + struct pt_regs *regs = (struct pt_regs *)current->thread->rsp0 -1; + color_printk(GREEN,BLACK,"sys_fork\n"); + return do_fork(regs,0,regs->rsp,0); +} + +unsigned long sys_vfork() +{ + struct pt_regs *regs = (struct pt_regs *)current->thread->rsp0 -1; + color_printk(GREEN,BLACK,"sys_vfork\n"); + return do_fork(regs,CLONE_VM | CLONE_FS | CLONE_SIGNAL,regs->rsp,0); +} + +unsigned long sys_execve() +{ + char * pathname = NULL; + long pathlen = 0; + long error = 0; + struct pt_regs *regs = (struct pt_regs *)current->thread->rsp0 -1; + + color_printk(GREEN,BLACK,"sys_execve\n"); + pathname = (char *)kmalloc(PAGE_4K_SIZE,0); + if(pathname == NULL) + return -ENOMEM; + memset(pathname,0,PAGE_4K_SIZE); + pathlen = strnlen_user((char *)regs->rdi,PAGE_4K_SIZE); + if(pathlen <= 0) + { + kfree(pathname); + return -EFAULT; + } + else if(pathlen >= PAGE_4K_SIZE) + { + kfree(pathname); + return -ENAMETOOLONG; + } + strncpy_from_user((char *)regs->rdi,pathname,pathlen); + + error = do_execve(regs,pathname,(char **)regs->rsi,NULL); + + kfree(pathname); + return error; +} + +unsigned long sys_exit(int exit_code) +{ + color_printk(GREEN,BLACK,"sys_exit\n"); + return do_exit(exit_code); +} + +/* + rusage reserved */ +unsigned long sys_wait4(unsigned long pid,int *status,int options,void *rusage) +{ + long retval = 0; + struct task_struct *child = NULL; + struct task_struct *tsk = NULL; -unsigned long sys_putstring(char *string) + color_printk(GREEN,BLACK,"sys_wait4\n"); + for(tsk = &init_task_union.task;tsk->next != &init_task_union.task;tsk = tsk->next) + { + if(tsk->next->pid == pid) + { + child = tsk->next; + break; + } + } + + if(child == NULL) + return -ECHILD; + if(options != 0) + return -EINVAL; + + if(child->state == TASK_ZOMBIE) + { + copy_to_user(&child->exit_code,status,sizeof(int)); + tsk->next = child->next; + exit_mm(child); + kfree(child); + return retval; + } + + interruptible_sleep_on(¤t->wait_childexit); + + copy_to_user(&child->exit_code,status,sizeof(long)); + tsk->next = child->next; + exit_mm(child); + kfree(child); + return retval; +} + +unsigned long sys_brk(unsigned long brk) { - color_printk(ORANGE,WHITE,string); + unsigned long new_brk = PAGE_2M_ALIGN(brk); + +// color_printk(GREEN,BLACK,"sys_brk\n"); +// color_printk(RED,BLACK,"brk:%#018lx,new_brk:%#018lx,current->mm->end_brk:%#018lx\n",brk,new_brk,current->mm->end_brk); + if(new_brk == 0) + return current->mm->start_brk; + if(new_brk < current->mm->end_brk) //release brk space + return 0; + + new_brk = do_brk(current->mm->end_brk,new_brk - current->mm->end_brk); //expand brk space + + current->mm->end_brk = new_brk; + return new_brk; +} + +unsigned long sys_reboot(unsigned long cmd,void * arg) +{ + color_printk(GREEN,BLACK,"sys_reboot\n"); + switch(cmd) + { + case SYSTEM_REBOOT: + io_out8(0x64,0xFE); + break; + + case SYSTEM_POWEROFF: + color_printk(RED,BLACK,"sys_reboot cmd SYSTEM_POWEROFF\n"); + break; + + default: + color_printk(RED,BLACK,"sys_reboot cmd ERROR!\n"); + break; + } return 0; } +unsigned long sys_chdir(char *filename) +{ + char * path = NULL; + long pathlen = 0; + struct dir_entry * dentry = NULL; + + color_printk(GREEN,BLACK,"sys_chdir\n"); + path = (char *)kmalloc(PAGE_4K_SIZE,0); + + if(path == NULL) + return -ENOMEM; + memset(path,0,PAGE_4K_SIZE); + pathlen = strnlen_user(filename,PAGE_4K_SIZE); + if(pathlen <= 0) + { + kfree(path); + return -EFAULT; + } + else if(pathlen >= PAGE_4K_SIZE) + { + kfree(path); + return -ENAMETOOLONG; + } + strncpy_from_user(filename,path,pathlen); + + dentry = path_walk(path,0); + kfree(path); + + if(dentry == NULL) + return -ENOENT; + if(dentry->dir_inode->attribute != FS_ATTR_DIR) + return -ENOTDIR; + return 0; +} + +unsigned long sys_getdents(int fd, void * dirent, long count) +{ + struct file * filp = NULL; + unsigned long ret = 0; + +// color_printk(GREEN,BLACK,"sys_getdents:%d\n",fd); + if(fd < 0 || fd > TASK_FILE_MAX) + return -EBADF; + if(count < 0) + return -EINVAL; + + filp = current->file_struct[fd]; + if(filp->f_ops && filp->f_ops->readdir) + ret = filp->f_ops->readdir(filp,dirent,&fill_dentry); + return ret; +} diff --git a/kernel/sys.h b/kernel/sys.h new file mode 100644 index 0000000000000000000000000000000000000000..be99aa81e11c6cf2c91159d3bad688b0969b711c --- /dev/null +++ b/kernel/sys.h @@ -0,0 +1,17 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __SYS_H__ + +#define __SYS_H__ + +#define SYSTEM_REBOOT (1UL << 0) +#define SYSTEM_POWEROFF (1UL << 1) + +#endif diff --git a/kernel/syscalls.c b/kernel/syscalls.c index 50892da599825c418ed8633ceaab41f4c98fcad4..8e415b10ecd46a4b9ddc59cfb0e524599a3b97ee 100644 --- a/kernel/syscalls.c +++ b/kernel/syscalls.c @@ -28,6 +28,3 @@ system_call_t system_call_table[MAX_SYSTEM_CALL_NR] = #include "syscalls.h" }; - - - diff --git a/kernel/syscalls.h b/kernel/syscalls.h index dcc6b929acb7b829642b6300cde59004d746294f..a087149c0c2e18cb5b837c848382fbc850a424f4 100644 --- a/kernel/syscalls.h +++ b/kernel/syscalls.h @@ -10,3 +10,21 @@ SYSCALL_COMMON(__NR_putstring,sys_putstring) +SYSCALL_COMMON(__NR_open,sys_open) +SYSCALL_COMMON(__NR_close,sys_close) +SYSCALL_COMMON(__NR_read,sys_read) +SYSCALL_COMMON(__NR_write,sys_write) +SYSCALL_COMMON(__NR_lseek,sys_lseek) + +SYSCALL_COMMON(__NR_fork,sys_fork) +SYSCALL_COMMON(__NR_vfork,sys_vfork) +SYSCALL_COMMON(__NR_execve,sys_execve) +SYSCALL_COMMON(__NR_exit,sys_exit) +SYSCALL_COMMON(__NR_wait4,sys_wait4) + +SYSCALL_COMMON(__NR_brk,sys_brk) +SYSCALL_COMMON(__NR_reboot,sys_reboot) + +SYSCALL_COMMON(__NR_chdir,sys_chdir) +SYSCALL_COMMON(__NR_getdents,sys_getdents) + diff --git a/kernel/task.c b/kernel/task.c index 22a380e090b253356019f4ac35c3baf65f02f3b8..038042390f60f88259acf6fa5a112028f9e02609 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -9,14 +9,19 @@ #include "task.h" #include "ptrace.h" -#include "printk.h" #include "lib.h" #include "memory.h" +#include "linkage.h" +#include "gate.h" +#include "schedule.h" +#include "printk.h" +#include "SMP.h" #include "unistd.h" - -union task_union init_task_union __attribute__((__section__ (".data.init_task"))) = {INIT_TASK(init_task_union.task)}; - -struct task_struct *init_task[NR_CPUS] = {&init_task_union.task,0}; +#include "stdio.h" +#include "sched.h" +#include "errno.h" +#include "fcntl.h" +#include "waitqueue.h" struct mm_struct init_mm = {0}; @@ -31,124 +36,186 @@ struct thread_struct init_thread = .error_code = 0 }; +union task_union init_task_union __attribute__((__section__ (".data.init_task"))) = {INIT_TASK(init_task_union.task)}; +struct task_struct *init_task[NR_CPUS] = {&init_task_union.task,0}; struct tss_struct init_tss[NR_CPUS] = { [0 ... NR_CPUS-1] = INIT_TSS }; -void user_level_function() +long global_pid; + +struct task_struct *get_task(long pid) { - int errno = 0; - char string[]="Hello World!\n"; - - color_printk(RED,BLACK,"user_level_function task is running\n"); - -// call sys_putstring - - __asm__ __volatile__ ( "pushq %%r10 \n\t" - "pushq %%r11 \n\t" - "leaq sysexit_return_address(%%rip), %%r10 \n\t" - "movq %%rsp, %%r11 \n\t" - "sysenter \n\t" - "sysexit_return_address: \n\t" - "xchgq %%rdx, %%r10 \n\t" - "xchgq %%rcx, %%r11 \n\t" - "popq %%r11 \n\t" - "popq %%r10 \n\t" - :"=a"(errno) - :"0"(__NR_putstring),"D"(string) - :"memory"); - - color_printk(RED,BLACK,"user_level_function task called sysenter,errno:%d\n",errno); - - while(1); + struct task_struct *tsk = NULL; + for(tsk = init_task_union.task.next;tsk != &init_task_union.task;tsk = tsk->next) + { + if(tsk->pid == pid) + return tsk; + } + return NULL; } +struct file * open_exec_file(char * path) +{ + struct dir_entry * dentry = NULL; + struct file * filp = NULL; + + dentry = path_walk(path,0); + + if(dentry == NULL) + return (void *)-ENOENT; + if(dentry->dir_inode->attribute == FS_ATTR_DIR) + return (void *)-ENOTDIR; + + filp = (struct file *)kmalloc(sizeof(struct file),0); + if(filp == NULL) + return (void *)-ENOMEM; -unsigned long do_execve(struct pt_regs * regs) + filp->position = 0; + filp->mode = 0; + filp->dentry = dentry; + filp->mode = O_RDONLY; + filp->f_ops = dentry->dir_inode->f_ops; + + return filp; +} + +unsigned long do_execve(struct pt_regs *regs,char *name,char *argv[],char *envp[]) { -// regs->rdx = 0x800000; //RIP -// regs->rcx = 0xa00000; //RSP - regs->r10 = 0x800000; //RIP - regs->r11 = 0xa00000; //RSP - regs->rax = 1; - regs->ds = 0; - regs->es = 0; - color_printk(RED,BLACK,"do_execve task is running\n"); + unsigned long code_start_addr = 0x800000; + unsigned long stack_start_addr = 0xa00000; + unsigned long brk_start_addr = 0xc00000; + unsigned long * tmp; + unsigned long * virtual = NULL; + struct Page * p = NULL; + struct file * filp = NULL; + unsigned long retval = 0; + long pos = 0; + + if(current->flags & PF_VFORK) + { + current->mm = (struct mm_struct *)kmalloc(sizeof(struct mm_struct),0); + memset(current->mm,0,sizeof(struct mm_struct)); + + current->mm->pgd = (pml4t_t *)Virt_To_Phy(kmalloc(PAGE_4K_SIZE,0)); + color_printk(RED,BLACK,"load_binary_file malloc new pgd:%#018lx\n",current->mm->pgd); + memset(Phy_To_Virt(current->mm->pgd),0,PAGE_4K_SIZE/2); + memcpy(Phy_To_Virt(init_task[SMP_cpu_id()]->mm->pgd)+256,Phy_To_Virt(current->mm->pgd)+256,PAGE_4K_SIZE/2); //copy kernel space + } + + tmp = Phy_To_Virt((unsigned long *)((unsigned long)current->mm->pgd & (~ 0xfffUL)) + ((code_start_addr >> PAGE_GDT_SHIFT) & 0x1ff)); + if(*tmp == NULL) + { + virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_mpl4t(tmp,mk_mpl4t(Virt_To_Phy(virtual),PAGE_USER_GDT)); + } + + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + ((code_start_addr >> PAGE_1G_SHIFT) & 0x1ff)); + if(*tmp == NULL) + { + virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_pdpt(tmp,mk_pdpt(Virt_To_Phy(virtual),PAGE_USER_Dir)); + } + + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + ((code_start_addr >> PAGE_2M_SHIFT) & 0x1ff)); + if(*tmp == NULL) + { + p = alloc_pages(ZONE_NORMAL,1,PG_PTable_Maped); + set_pdt(tmp,mk_pdt(p->PHY_address,PAGE_USER_Page)); + } + + __asm__ __volatile__ ("movq %0, %%cr3 \n\t"::"r"(current->mm->pgd):"memory"); + + filp = open_exec_file(name); + if((unsigned long)filp > -0x1000UL) + return (unsigned long)filp; + + if(!(current->flags & PF_KTHREAD)) + current->addr_limit = TASK_SIZE; + + current->mm->start_code = code_start_addr; + current->mm->end_code = 0; + current->mm->start_data = 0; + current->mm->end_data = 0; + current->mm->start_rodata = 0; + current->mm->end_rodata = 0; + current->mm->start_bss = code_start_addr + filp->dentry->dir_inode->file_size; + current->mm->end_bss = stack_start_addr; + current->mm->start_brk = brk_start_addr; + current->mm->end_brk = brk_start_addr; + current->mm->start_stack = stack_start_addr; + + exit_files(current); + + current->flags &= ~PF_VFORK; + + if(argv != NULL) + { + int argc = 0; + int len = 0; + int i = 0; + char ** dargv = (char **)(stack_start_addr - 10 * sizeof(char *)); + pos = (unsigned long)dargv; + + for(i = 0;i<10 && argv[i] != NULL;i++) + { + len = strnlen_user(argv[i],1024) + 1; + strcpy((char *)(pos - len),argv[i]); + dargv[i] = (char *)(pos - len); + pos -= len; + } + stack_start_addr = pos - 10; + regs->rdi = i; //argc + regs->rsi = (unsigned long)dargv; //argv + } + + memset((void *)code_start_addr,0,stack_start_addr - code_start_addr); + + pos = 0; + retval = filp->f_ops->read(filp,(void *)code_start_addr,filp->dentry->dir_inode->file_size,&pos); + + __asm__ __volatile__ ("movq %0,%%gs ;movq %0,%%fs ;"::"r"(0UL)); + + regs->ds = USER_DS; + regs->es = USER_DS; + regs->ss = USER_DS; + regs->cs = USER_CS; +// regs->rip = new_rip; +// regs->rsp = new_rsp; + regs->r10 = code_start_addr; + regs->r11 = stack_start_addr; + regs->rax = 1; - memcpy(user_level_function,(void *)0x800000,1024); + color_printk(RED,BLACK,"do_execve task is running\n"); - return 0; + return retval; } unsigned long init(unsigned long arg) { - struct pt_regs *regs; + DISK1_FAT32_FS_init(); color_printk(RED,BLACK,"init task is running,arg:%#018lx\n",arg); current->thread->rip = (unsigned long)ret_system_call; current->thread->rsp = (unsigned long)current + STACK_SIZE - sizeof(struct pt_regs); - regs = (struct pt_regs *)current->thread->rsp; + current->thread->gs = USER_DS; + current->thread->fs = USER_DS; + current->flags &= ~PF_KTHREAD; __asm__ __volatile__ ( "movq %1, %%rsp \n\t" "pushq %2 \n\t" "jmp do_execve \n\t" - ::"D"(regs),"m"(current->thread->rsp),"m"(current->thread->rip):"memory"); + : + :"D"(current->thread->rsp),"m"(current->thread->rsp),"m"(current->thread->rip),"S"("/init.bin"),"d"(NULL),"c"(NULL) + :"memory" + ); return 1; } - -unsigned long do_fork(struct pt_regs * regs, unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size) -{ - struct task_struct *tsk = NULL; - struct thread_struct *thd = NULL; - struct Page *p = NULL; - - int i = 1/0; - color_printk(WHITE,BLACK,"alloc_pages,bitmap:%#018lx\n",*memory_management_struct.bits_map); - - p = alloc_pages(ZONE_NORMAL,1,PG_PTable_Maped | PG_Active | PG_Kernel); - - color_printk(WHITE,BLACK,"alloc_pages,bitmap:%#018lx\n",*memory_management_struct.bits_map); - - tsk = (struct task_struct *)Phy_To_Virt(p->PHY_address); - color_printk(WHITE,BLACK,"struct task_struct address:%#018lx\n",(unsigned long)tsk); - - memset(tsk,0,sizeof(*tsk)); - *tsk = *current; - - list_init(&tsk->list); - list_add_to_before(&init_task_union.task.list,&tsk->list); - tsk->pid++; - tsk->state = TASK_UNINTERRUPTIBLE; - - thd = (struct thread_struct *)(tsk + 1); - tsk->thread = thd; - - memcpy(regs,(void *)((unsigned long)tsk + STACK_SIZE - sizeof(struct pt_regs)),sizeof(struct pt_regs)); - - thd->rsp0 = (unsigned long)tsk + STACK_SIZE; - thd->rip = regs->rip; - thd->rsp = (unsigned long)tsk + STACK_SIZE - sizeof(struct pt_regs); - - if(!(tsk->flags & PF_KTHREAD)) - thd->rip = regs->rip = (unsigned long)ret_system_call; - - tsk->state = TASK_RUNNING; - - return 0; -} - - - -unsigned long do_exit(unsigned long code) -{ - color_printk(RED,BLACK,"exit task is running,arg:%#018lx\n",code); - while(1); -} - - void kernel_thread_func(void); __asm__ ( "kernel_thread_func: \n\t" @@ -180,6 +247,262 @@ __asm__ ( ); +inline void wakeup_process(struct task_struct *tsk) +{ + tsk->state = TASK_RUNNING; + insert_task_queue(tsk); + current->flags |= NEED_SCHEDULE; +} + +unsigned long copy_flags(unsigned long clone_flags,struct task_struct *tsk) +{ + if(clone_flags & CLONE_VM) + tsk->flags |= PF_VFORK; + return 0; +} + +unsigned long copy_files(unsigned long clone_flags,struct task_struct *tsk) +{ + int error = 0; + int i = 0; + if(clone_flags & CLONE_FS) + goto out; + + for(i = 0;ifile_struct[i] != NULL) + { + tsk->file_struct[i] = (struct file *)kmalloc(sizeof(struct file),0); + memcpy(current->file_struct[i],tsk->file_struct[i],sizeof(struct file)); + } +out: + return error; +} +void exit_files(struct task_struct *tsk) +{ + int i = 0; + if(tsk->flags & PF_VFORK) + ; + else + for(i = 0;ifile_struct[i] != NULL) + { + kfree(tsk->file_struct[i]); + } + + memset(tsk->file_struct,0,sizeof(struct file *) * TASK_FILE_MAX); //clear current->file_struct +} + + +unsigned long copy_mm(unsigned long clone_flags,struct task_struct *tsk) +{ + int error = 0; + struct mm_struct *newmm = NULL; + unsigned long code_start_addr = 0x800000; + unsigned long stack_start_addr = 0xa00000; + unsigned long brk_start_addr = 0xc00000; + unsigned long * tmp; + unsigned long * virtual = NULL; + struct Page * p = NULL; + + if(clone_flags & CLONE_VM) + { + newmm = current->mm; + goto out; + } + + newmm = (struct mm_struct *)kmalloc(sizeof(struct mm_struct),0); + memcpy(current->mm,newmm,sizeof(struct mm_struct)); + + newmm->pgd = (pml4t_t *)Virt_To_Phy(kmalloc(PAGE_4K_SIZE,0)); + memcpy(Phy_To_Virt(init_task[SMP_cpu_id()]->mm->pgd)+256,Phy_To_Virt(newmm->pgd)+256,PAGE_4K_SIZE/2); //copy kernel space + + memset(Phy_To_Virt(newmm->pgd),0,PAGE_4K_SIZE/2); //copy user code & data & bss space + + tmp = Phy_To_Virt((unsigned long *)((unsigned long)newmm->pgd & (~ 0xfffUL)) + ((code_start_addr >> PAGE_GDT_SHIFT) & 0x1ff)); + virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_mpl4t(tmp,mk_mpl4t(Virt_To_Phy(virtual),PAGE_USER_GDT)); + + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + ((code_start_addr >> PAGE_1G_SHIFT) & 0x1ff)); + virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_pdpt(tmp,mk_pdpt(Virt_To_Phy(virtual),PAGE_USER_Dir)); + + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + ((code_start_addr >> PAGE_2M_SHIFT) & 0x1ff)); + p = alloc_pages(ZONE_NORMAL,1,PG_PTable_Maped); + set_pdt(tmp,mk_pdt(p->PHY_address,PAGE_USER_Page)); + + memcpy((void *)code_start_addr,Phy_To_Virt(p->PHY_address),stack_start_addr - code_start_addr); + + ////copy user brk space + if(current->mm->end_brk - current->mm->start_brk != 0) + { + tmp = Phy_To_Virt((unsigned long *)((unsigned long)newmm->pgd & (~ 0xfffUL)) + ((brk_start_addr >> PAGE_GDT_SHIFT) & 0x1ff)); + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + ((brk_start_addr >> PAGE_1G_SHIFT) & 0x1ff)); + tmp = Phy_To_Virt((unsigned long *)(*tmp & (~ 0xfffUL)) + ((brk_start_addr >> PAGE_2M_SHIFT) & 0x1ff)); + p = alloc_pages(ZONE_NORMAL,1,PG_PTable_Maped); + set_pdt(tmp,mk_pdt(p->PHY_address,PAGE_USER_Page)); + + memcpy((void *)brk_start_addr,Phy_To_Virt(p->PHY_address),PAGE_2M_SIZE); + } + +out: + tsk->mm = newmm; + return error; +} +void exit_mm(struct task_struct *tsk) +{ + unsigned long code_start_addr = 0x800000; + unsigned long * tmp4; + unsigned long * tmp3; + unsigned long * tmp2; + + if(tsk->flags & PF_VFORK) + return; + + if(tsk->mm->pgd != NULL) + { + tmp4 = Phy_To_Virt((unsigned long *)((unsigned long)tsk->mm->pgd & (~ 0xfffUL)) + ((code_start_addr >> PAGE_GDT_SHIFT) & 0x1ff)); + tmp3 = Phy_To_Virt((unsigned long *)(*tmp4 & (~ 0xfffUL)) + ((code_start_addr >> PAGE_1G_SHIFT) & 0x1ff)); + tmp2 = Phy_To_Virt((unsigned long *)(*tmp3 & (~ 0xfffUL)) + ((code_start_addr >> PAGE_2M_SHIFT) & 0x1ff)); + + free_pages(Phy_to_2M_Page(*tmp2),1); + kfree(Phy_To_Virt(*tmp3)); + kfree(Phy_To_Virt(*tmp4)); + kfree(Phy_To_Virt(tsk->mm->pgd)); + } + if(tsk->mm != NULL) + kfree(tsk->mm); +} + + +unsigned long copy_thread(unsigned long clone_flags,unsigned long stack_start,unsigned long stack_size,struct task_struct *tsk,struct pt_regs * regs) +{ + struct thread_struct *thd = NULL; + struct pt_regs *childregs = NULL; + + thd = (struct thread_struct *)(tsk + 1); + memset(thd,0,sizeof(*thd)); + tsk->thread = thd; + + childregs = (struct pt_regs *)((unsigned long)tsk + STACK_SIZE) - 1; + + memcpy(regs,childregs,sizeof(struct pt_regs)); + childregs->rax = 0; + childregs->rsp = stack_start; + + thd->rsp0 = (unsigned long)tsk + STACK_SIZE; + thd->rsp = (unsigned long)childregs; + thd->fs = current->thread->fs; + thd->gs = current->thread->gs; + + if(tsk->flags & PF_KTHREAD) + thd->rip = (unsigned long)kernel_thread_func; + else + thd->rip = (unsigned long)ret_system_call; + + color_printk(WHITE,BLACK,"current user ret addr:%#018lx,rsp:%#018lx\n",regs->r10,regs->r11); + color_printk(WHITE,BLACK,"new user ret addr:%#018lx,rsp:%#018lx\n",childregs->r10,childregs->r11); + + return 0; +} +void exit_thread(struct task_struct *tsk){} + + +unsigned long do_fork(struct pt_regs * regs, unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size) +{ + int retval = 0; + struct task_struct *tsk = NULL; + +// alloc & copy task struct + tsk = (struct task_struct *)kmalloc(STACK_SIZE,0); + color_printk(WHITE,BLACK,"struct task_struct address:%#018lx\n",(unsigned long)tsk); + + if(tsk == NULL) + { + retval = -EAGAIN; + goto alloc_copy_task_fail; + } + + memset(tsk,0,sizeof(*tsk)); + memcpy(current,tsk,sizeof(struct task_struct)); + + list_init(&tsk->list); + tsk->priority = 2; + tsk->pid = global_pid++; + tsk->preempt_count = 0; + tsk->cpu_id = SMP_cpu_id(); + tsk->state = TASK_UNINTERRUPTIBLE; + tsk->next = init_task_union.task.next; + init_task_union.task.next = tsk; + tsk->parent = current; + wait_queue_init(&tsk->wait_childexit,NULL); + + retval = -ENOMEM; +// copy flags + if(copy_flags(clone_flags,tsk)) + goto copy_flags_fail; + +// copy mm struct + if(copy_mm(clone_flags,tsk)) + goto copy_mm_fail; + +// copy file struct + if(copy_files(clone_flags,tsk)) + goto copy_files_fail; + +// copy thread struct + if(copy_thread(clone_flags,stack_start,stack_size,tsk,regs)) + goto copy_thread_fail; + + retval = tsk->pid; + + wakeup_process(tsk); + +fork_ok: + return retval; + + +copy_thread_fail: + exit_thread(tsk); +copy_files_fail: + exit_files(tsk); +copy_mm_fail: + exit_mm(tsk); +copy_flags_fail: +alloc_copy_task_fail: + kfree(tsk); + + return retval; +} + +void exit_notify(void) +{ + wakeup(¤t->parent->wait_childexit,TASK_INTERRUPTIBLE); +} + + +unsigned long do_exit(unsigned long exit_code) +{ + struct task_struct *tsk = current; + color_printk(RED,BLACK,"exit task is running,arg:%#018lx\n",exit_code); + +do_exit_again: + + cli(); + tsk->state = TASK_ZOMBIE; + tsk->exit_code = exit_code; + exit_thread(tsk); + exit_files(tsk); + sti(); + + exit_notify(); + schedule(); + + goto do_exit_again; + return 0; +} + int kernel_thread(unsigned long (* fn)(unsigned long), unsigned long arg, unsigned long flags) { @@ -196,17 +519,17 @@ int kernel_thread(unsigned long (* fn)(unsigned long), unsigned long arg, unsign regs.rflags = (1 << 9); regs.rip = (unsigned long)kernel_thread_func; - return do_fork(®s,flags,0,0); + return do_fork(®s,flags | CLONE_VM,0,0); } - +inline void switch_mm(struct task_struct *prev,struct task_struct *next) +{ + __asm__ __volatile__ ("movq %0, %%cr3 \n\t"::"r"(next->mm->pgd):"memory"); +} inline void __switch_to(struct task_struct *prev,struct task_struct *next) { - - init_tss[0].rsp0 = next->thread->rsp0; - - set_tss64(init_tss[0].rsp0, init_tss[0].rsp1, init_tss[0].rsp2, init_tss[0].ist1, init_tss[0].ist2, init_tss[0].ist3, init_tss[0].ist4, init_tss[0].ist5, init_tss[0].ist6, init_tss[0].ist7); + init_tss[SMP_cpu_id()].rsp0 = next->thread->rsp0; __asm__ __volatile__("movq %%fs, %0 \n\t":"=a"(prev->thread->fs)); __asm__ __volatile__("movq %%gs, %0 \n\t":"=a"(prev->thread->gs)); @@ -214,8 +537,7 @@ inline void __switch_to(struct task_struct *prev,struct task_struct *next) __asm__ __volatile__("movq %0, %%fs \n\t"::"a"(next->thread->fs)); __asm__ __volatile__("movq %0, %%gs \n\t"::"a"(next->thread->gs)); - color_printk(WHITE,BLACK,"prev->thread->rsp0:%#018lx\n",prev->thread->rsp0); - color_printk(WHITE,BLACK,"next->thread->rsp0:%#018lx\n",next->thread->rsp0); + wrmsr(0x175,next->thread->rsp0); } /* @@ -224,7 +546,25 @@ inline void __switch_to(struct task_struct *prev,struct task_struct *next) void task_init() { - struct task_struct *p = NULL; + unsigned long * tmp = NULL; + unsigned long * vaddr = NULL; + int i = 0; + + vaddr = (unsigned long *)Phy_To_Virt((unsigned long)Get_gdt() & (~ 0xfffUL)); + + *vaddr = 0UL; + + for(i = 256;i<512;i++) + { + tmp = vaddr + i; + + if(*tmp == 0) + { + unsigned long * virtual = kmalloc(PAGE_4K_SIZE,0); + memset(virtual,0,PAGE_4K_SIZE); + set_mpl4t(tmp,mk_mpl4t(Virt_To_Phy(virtual),PAGE_KERNEL_GDT)); + } + } init_mm.pgd = (pml4t_t *)Get_gdt(); @@ -235,10 +575,13 @@ void task_init() init_mm.end_data = memory_management_struct.end_data; init_mm.start_rodata = (unsigned long)&_rodata; - init_mm.end_rodata = (unsigned long)&_erodata; + init_mm.end_rodata = memory_management_struct.end_rodata; + + init_mm.start_bss = (unsigned long)&_bss; + init_mm.end_bss = (unsigned long)&_ebss; - init_mm.start_brk = 0; - init_mm.end_brk = memory_management_struct.end_brk; + init_mm.start_brk = memory_management_struct.start_brk; + init_mm.end_brk = current->addr_limit; init_mm.start_stack = _stack_start; @@ -247,18 +590,16 @@ void task_init() wrmsr(0x176,(unsigned long)system_call); // init_thread,init_tss - set_tss64(init_thread.rsp0, init_tss[0].rsp1, init_tss[0].rsp2, init_tss[0].ist1, init_tss[0].ist2, init_tss[0].ist3, init_tss[0].ist4, init_tss[0].ist5, init_tss[0].ist6, init_tss[0].ist7); +// set_tss64(TSS64_Table,init_thread.rsp0, init_tss[0].rsp1, init_tss[0].rsp2, init_tss[0].ist1, init_tss[0].ist2, init_tss[0].ist3, init_tss[0].ist4, init_tss[0].ist5, init_tss[0].ist6, init_tss[0].ist7); - init_tss[0].rsp0 = init_thread.rsp0; + init_tss[SMP_cpu_id()].rsp0 = init_thread.rsp0; list_init(&init_task_union.task.list); - kernel_thread(init,10,CLONE_FS | CLONE_FILES | CLONE_SIGNAL); + kernel_thread(init,10,CLONE_FS | CLONE_SIGNAL); + init_task_union.task.preempt_count = 0; init_task_union.task.state = TASK_RUNNING; - - p = container_of(list_next(¤t->list),struct task_struct,list); - - switch_to(current,p); + init_task_union.task.cpu_id = 0; } diff --git a/kernel/task.h b/kernel/task.h index 38a60cdda65f5608d4f632d433077666c2ce3fdd..dc115c23005e2f5d245bc3e1557454d7a733aaed 100644 --- a/kernel/task.h +++ b/kernel/task.h @@ -15,6 +15,8 @@ #include "cpu.h" #include "lib.h" #include "ptrace.h" +#include "VFS.h" +#include "waitqueue.h" #define KERNEL_CS (0x08) #define KERNEL_DS (0x10) @@ -22,10 +24,6 @@ #define USER_CS (0x28) #define USER_DS (0x30) -#define CLONE_FS (1 << 0) -#define CLONE_FILES (1 << 1) -#define CLONE_SIGNAL (1 << 2) - // stack size 32K #define STACK_SIZE 32768 @@ -45,6 +43,7 @@ extern long kallsyms_index[] __attribute__((weak)); extern char* kallsyms_names __attribute__((weak)); extern unsigned long _stack_start; +extern long global_pid; /* @@ -68,8 +67,9 @@ struct mm_struct unsigned long start_code,end_code; unsigned long start_data,end_data; unsigned long start_rodata,end_rodata; + unsigned long start_bss,end_bss; unsigned long start_brk,end_brk; - unsigned long start_stack; + unsigned long start_stack; }; /* @@ -95,46 +95,68 @@ struct thread_struct */ -#define PF_KTHREAD (1 << 0) +#define TASK_FILE_MAX 10 struct task_struct { - struct List list; volatile long state; unsigned long flags; + long preempt_count; + long signal; + long cpu_id; //CPU ID struct mm_struct *mm; struct thread_struct *thread; + struct List list; + unsigned long addr_limit; /*0x0000,0000,0000,0000 - 0x0000,7fff,ffff,ffff user*/ /*0xffff,8000,0000,0000 - 0xffff,ffff,ffff,ffff kernel*/ - long pid; + long priority; + long vrun_time; - long counter; + long exit_code; - long signal; + struct file * file_struct[TASK_FILE_MAX]; - long priority; + wait_queue_T wait_childexit; + struct task_struct *next; + struct task_struct *parent; }; +///////struct task_struct->flags: + +#define PF_KTHREAD (1UL << 0) +#define NEED_SCHEDULE (1UL << 1) +#define PF_VFORK (1UL << 2) + + union task_union { struct task_struct task; unsigned long stack[STACK_SIZE / sizeof(unsigned long)]; }__attribute__((aligned (8))); //8Bytes align + + #define INIT_TASK(tsk) \ { \ .state = TASK_UNINTERRUPTIBLE, \ .flags = PF_KTHREAD, \ + .preempt_count = 0, \ + .signal = 0, \ + .cpu_id = 0, \ .mm = &init_mm, \ .thread = &init_thread, \ - .addr_limit = 0xffff800000000000, \ + .addr_limit = 0xffffffffffffffff, \ .pid = 0, \ - .counter = 1, \ - .signal = 0, \ - .priority = 0 \ + .priority = 2, \ + .vrun_time = 0, \ + .exit_code = 0, \ + .file_struct = {0}, \ + .next = &tsk, \ + .parent = &tsk, \ } /* @@ -178,6 +200,7 @@ struct tss_struct .iomapbaseaddr = 0 \ } + /* */ @@ -223,10 +246,20 @@ do{ \ /* */ +long get_pid(); +struct task_struct *get_task(long pid); + +inline void wakeup_process(struct task_struct *tsk); +void exit_files(struct task_struct *tsk); unsigned long do_fork(struct pt_regs * regs, unsigned long clone_flags, unsigned long stack_start, unsigned long stack_size); +unsigned long do_execve(struct pt_regs *regs,char *name,char *argv[],char *envp[]); +unsigned long do_exit(unsigned long exit_code); + void task_init(); +inline void switch_mm(struct task_struct *prev,struct task_struct *next); + extern void ret_system_call(void); extern void system_call(void); diff --git a/kernel/time.c b/kernel/time.c new file mode 100644 index 0000000000000000000000000000000000000000..cdb114fc7d0052c159bfe04c074c983d5155f1de --- /dev/null +++ b/kernel/time.c @@ -0,0 +1,32 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "time.h" +#include "lib.h" + +struct time time; + +#define CMOS_READ(addr) ({ \ +io_out8(0x70,0x80 | addr); \ +io_in8(0x71); \ +}) + +void get_cmos_time(struct time *time) +{ + do + { time->year = CMOS_READ(0x09) + CMOS_READ(0x32) * 0x100; + time->month = CMOS_READ(0x08); + time->day = CMOS_READ(0x07); + time->hour = CMOS_READ(0x04); + time->minute = CMOS_READ(0x02); + time->second = CMOS_READ(0x00); + }while(time->second != CMOS_READ(0x00)); + + io_out8(0x70,0x00); +} diff --git a/kernel/time.h b/kernel/time.h new file mode 100644 index 0000000000000000000000000000000000000000..d65e00a767ba306631e7da458eb2526562007a03 --- /dev/null +++ b/kernel/time.h @@ -0,0 +1,30 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __TIME_H__ + +#define __TIME_H__ + +struct time +{ + int second; //00 + int minute; //02 + int hour; //04 + int day; //07 + int month; //08 + int year; //09+32 +}; + +extern struct time time; + +#define BCD2BIN(value) (((value) & 0xf) + ((value) >> 4 ) * 10) + +void get_cmos_time(struct time *time); + +#endif diff --git a/kernel/timer.c b/kernel/timer.c new file mode 100644 index 0000000000000000000000000000000000000000..8e0486fc2721536453c140aac8e936e6afbc2315 --- /dev/null +++ b/kernel/timer.c @@ -0,0 +1,77 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "timer.h" +#include "softirq.h" +#include "printk.h" +#include "lib.h" +#include "memory.h" + +unsigned long volatile jiffies = 0; +struct timer_list timer_list_head; + +void init_timer(struct timer_list * timer,void (* func)(void * data),void *data,unsigned long expire_jiffies) +{ + list_init(&timer->list); + timer->func = func; + timer->data = data; + timer->expire_jiffies = jiffies + expire_jiffies; +} + +void add_timer(struct timer_list * timer) +{ + struct timer_list * tmp = container_of(list_next(&timer_list_head.list),struct timer_list,list); + + if(list_is_empty(&timer_list_head.list)) + { + + } + else + { + while(tmp->expire_jiffies < timer->expire_jiffies) + tmp = container_of(list_next(&tmp->list),struct timer_list,list); + } + + list_add_to_behind(&tmp->list,&timer->list); +} + +void del_timer(struct timer_list * timer) +{ + list_del(&timer->list); +} + +void test_timer(void * data) +{ + color_printk(BLUE,WHITE,"test_timer"); +} + +void timer_init() +{ + struct timer_list *tmp = NULL; + jiffies = 0; + init_timer(&timer_list_head,NULL,NULL,-1UL); + register_softirq(0,&do_timer,NULL); + + tmp = (struct timer_list *)kmalloc(sizeof(struct timer_list),0); + init_timer(tmp,&test_timer,NULL,5); + add_timer(tmp); +} + +void do_timer(void * data) +{ + struct timer_list * tmp = container_of(list_next(&timer_list_head.list),struct timer_list,list); + while((!list_is_empty(&timer_list_head.list)) && (tmp->expire_jiffies <= jiffies)) + { + del_timer(tmp); + tmp->func(tmp->data); + tmp = container_of(list_next(&timer_list_head.list),struct timer_list,list); + } + + color_printk(RED,WHITE,"(HPET:%ld)",jiffies); +} diff --git a/kernel/timer.h b/kernel/timer.h new file mode 100644 index 0000000000000000000000000000000000000000..d992fe38975746282da1315fe5ef45c90b38635a --- /dev/null +++ b/kernel/timer.h @@ -0,0 +1,38 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __TIMER_H__ + +#define __TIMER_H__ + +#include "lib.h" + +extern unsigned long volatile jiffies; + +struct timer_list +{ + struct List list; + unsigned long expire_jiffies; + void (* func)(void * data); + void *data; +}; + +extern struct timer_list timer_list_head; + +void init_timer(struct timer_list * timer,void (* func)(void * data),void *data,unsigned long expire_jiffies); + +void add_timer(struct timer_list * timer); + +void del_timer(struct timer_list * timer); + +void timer_init(); + +void do_timer(); + +#endif diff --git a/kernel/trap.c b/kernel/trap.c index 35aa7e2baeeab23129e7dfcef73ef6dbc9f04b11..1fe1ac66a29b5f3d10d32c224469027aedf8d173 100644 --- a/kernel/trap.c +++ b/kernel/trap.c @@ -10,6 +10,8 @@ #include "trap.h" #include "gate.h" #include "ptrace.h" +#include "printk.h" +#include "SMP.h" #include "task.h" int lookup_kallsyms(unsigned long address,int level) @@ -39,8 +41,6 @@ void backtrace(struct pt_regs * regs) unsigned long ret_address = regs->rip; int i = 0; - color_printk(RED,BLACK,"====================== Task Struct Information =====================\n"); - color_printk(RED,BLACK,"regs->rsp:%#018lx,current->thread->rsp0:%#018lx,current:%#018lx\n",regs->rsp,current->thread->rsp0,current); color_printk(RED,BLACK,"====================== Kernel Stack Backtrace ======================\n"); for(i = 0;i<10;i++) @@ -55,16 +55,24 @@ void backtrace(struct pt_regs * regs) } } +void display_regs(struct pt_regs * regs) +{ + color_printk(RED,BLACK,"CS:%#010x,SS:%#010x\nDS:%#010x,ES:%#010x\nRFLAGS:%#018lx\n",regs->cs,regs->ss,regs->ds,regs->es,regs->rflags); + color_printk(RED,BLACK,"RAX:%#018lx,RBX:%#018lx,RCX:%#018lx,RDX:%#018lx\nRSP:%#018lx,RBP:%#018lx,RIP:%#018lx\nRSI:%#018lx,RDI:%#018lx\n",regs->rax,regs->rbx,regs->rcx,regs->rdx,regs->rsp,regs->rbp,regs->rip,regs->rsi,regs->rdi); + color_printk(RED,BLACK,"R8 :%#018lx,R9 :%#018lx\nR10:%#018lx,R11:%#018lx\nR12:%#018lx,R13:%#018lx\nR14:%#018lx,R15:%#018lx\n",regs->r8,regs->r9,regs->r10,regs->r11,regs->r12,regs->r13,regs->r14,regs->r15); + backtrace(regs); +} + /* 0 */ void do_divide_error(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_divide_error(0),ERROR_CODE:%#018lx\n",error_code); - backtrace(regs); + color_printk(RED,BLACK,"do_divide_error(0),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); while(1) - ; + hlt(); } /* @@ -73,8 +81,10 @@ void do_divide_error(struct pt_regs * regs,unsigned long error_code) void do_debug(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_debug(1),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_debug(1),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -83,8 +93,10 @@ void do_debug(struct pt_regs * regs,unsigned long error_code) void do_nmi(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_nmi(2),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_nmi(2),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -93,8 +105,10 @@ void do_nmi(struct pt_regs * regs,unsigned long error_code) void do_int3(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_int3(3),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_int3(3),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -103,8 +117,10 @@ void do_int3(struct pt_regs * regs,unsigned long error_code) void do_overflow(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_overflow(4),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_overflow(4),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -113,8 +129,10 @@ void do_overflow(struct pt_regs * regs,unsigned long error_code) void do_bounds(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_bounds(5),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_bounds(5),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code ,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -123,8 +141,10 @@ void do_bounds(struct pt_regs * regs,unsigned long error_code) void do_undefined_opcode(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_undefined_opcode(6),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_undefined_opcode(6),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -133,8 +153,10 @@ void do_undefined_opcode(struct pt_regs * regs,unsigned long error_code) void do_dev_not_available(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_dev_not_available(7),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_dev_not_available(7),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -143,8 +165,10 @@ void do_dev_not_available(struct pt_regs * regs,unsigned long error_code) void do_double_fault(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_double_fault(8),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_double_fault(8),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -153,8 +177,10 @@ void do_double_fault(struct pt_regs * regs,unsigned long error_code) void do_coprocessor_segment_overrun(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_coprocessor_segment_overrun(9),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_coprocessor_segment_overrun(9),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -163,7 +189,7 @@ void do_coprocessor_segment_overrun(struct pt_regs * regs,unsigned long error_co void do_invalid_TSS(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_invalid_TSS(10),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); + color_printk(RED,BLACK,"do_invalid_TSS(10),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); if(error_code & 0x01) color_printk(RED,BLACK,"The exception occurred during delivery of an event external to the program,such as an interrupt or an earlier exception.\n"); @@ -181,7 +207,9 @@ void do_invalid_TSS(struct pt_regs * regs,unsigned long error_code) color_printk(RED,BLACK,"Segment Selector Index:%#010x\n",error_code & 0xfff8); - while(1); + display_regs(regs); + while(1) + hlt(); } /* @@ -190,7 +218,7 @@ void do_invalid_TSS(struct pt_regs * regs,unsigned long error_code) void do_segment_not_present(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_segment_not_present(11),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); + color_printk(RED,BLACK,"do_segment_not_present(11),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); if(error_code & 0x01) color_printk(RED,BLACK,"The exception occurred during delivery of an event external to the program,such as an interrupt or an earlier exception.\n"); @@ -208,7 +236,9 @@ void do_segment_not_present(struct pt_regs * regs,unsigned long error_code) color_printk(RED,BLACK,"Segment Selector Index:%#010x\n",error_code & 0xfff8); - while(1); + display_regs(regs); + while(1) + hlt(); } /* @@ -217,7 +247,7 @@ void do_segment_not_present(struct pt_regs * regs,unsigned long error_code) void do_stack_segment_fault(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_stack_segment_fault(12),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); + color_printk(RED,BLACK,"do_stack_segment_fault(12),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); if(error_code & 0x01) color_printk(RED,BLACK,"The exception occurred during delivery of an event external to the program,such as an interrupt or an earlier exception.\n"); @@ -235,7 +265,9 @@ void do_stack_segment_fault(struct pt_regs * regs,unsigned long error_code) color_printk(RED,BLACK,"Segment Selector Index:%#010x\n",error_code & 0xfff8); - while(1); + display_regs(regs); + while(1) + hlt(); } /* @@ -244,7 +276,7 @@ void do_stack_segment_fault(struct pt_regs * regs,unsigned long error_code) void do_general_protection(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_general_protection(13),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); + color_printk(RED,BLACK,"do_general_protection(13),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); if(error_code & 0x01) color_printk(RED,BLACK,"The exception occurred during delivery of an event external to the program,such as an interrupt or an earlier exception.\n"); @@ -262,7 +294,9 @@ void do_general_protection(struct pt_regs * regs,unsigned long error_code) color_printk(RED,BLACK,"Segment Selector Index:%#010x\n",error_code & 0xfff8); - while(1); + display_regs(regs); + while(1) + hlt(); } /* @@ -275,7 +309,7 @@ void do_page_fault(struct pt_regs * regs,unsigned long error_code) __asm__ __volatile__("movq %%cr2, %0":"=r"(cr2)::"memory"); - color_printk(RED,BLACK,"do_page_fault(14),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); + color_printk(RED,BLACK,"do_page_fault(14),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); if(!(error_code & 0x01)) color_printk(RED,BLACK,"Page Not-Present,\t"); @@ -300,7 +334,9 @@ void do_page_fault(struct pt_regs * regs,unsigned long error_code) color_printk(RED,BLACK,"CR2:%#018lx\n",cr2); - while(1); + display_regs(regs); + while(1) + hlt(); } /* @@ -309,8 +345,10 @@ void do_page_fault(struct pt_regs * regs,unsigned long error_code) void do_x87_FPU_error(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_x87_FPU_error(16),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_x87_FPU_error(16),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -319,8 +357,10 @@ void do_x87_FPU_error(struct pt_regs * regs,unsigned long error_code) void do_alignment_check(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_alignment_check(17),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_alignment_check(17),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -329,8 +369,10 @@ void do_alignment_check(struct pt_regs * regs,unsigned long error_code) void do_machine_check(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_machine_check(18),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_machine_check(18),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -339,8 +381,10 @@ void do_machine_check(struct pt_regs * regs,unsigned long error_code) void do_SIMD_exception(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_SIMD_exception(19),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_SIMD_exception(19),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -349,8 +393,10 @@ void do_SIMD_exception(struct pt_regs * regs,unsigned long error_code) void do_virtualization_exception(struct pt_regs * regs,unsigned long error_code) { - color_printk(RED,BLACK,"do_virtualization_exception(20),ERROR_CODE:%#018lx,RSP:%#018lx,RIP:%#018lx\n",error_code , regs->rsp , regs->rip); - while(1); + color_printk(RED,BLACK,"do_virtualization_exception(20),ERROR_CODE:%#018lx,CPU:%#010x,PID:%#010x\n",error_code,SMP_cpu_id(),current->pid); + display_regs(regs); + while(1) + hlt(); } /* @@ -381,7 +427,7 @@ void sys_vector_init() set_trap_gate(19,0,SIMD_exception); set_trap_gate(20,0,virtualization_exception); - //set_system_gate(SYSTEM_CALL_VECTOR,0,system_call); + //set_system_gate(SYSTEM_CALL_VECTOR,7,system_call); } diff --git a/kernel/trap.h b/kernel/trap.h index ed4ad79b05541c3ede969e24ec228d498e413d97..93d986295f66346e6b72440e892bb580cde5c0bb 100644 --- a/kernel/trap.h +++ b/kernel/trap.h @@ -11,10 +11,6 @@ #define __TRAP_H__ -#include "linkage.h" -#include "printk.h" -#include "lib.h" - /* */ @@ -40,8 +36,6 @@ void SIMD_exception(); void virtualization_exception(); - - /* */ diff --git a/kernel/unistd.h b/kernel/unistd.h index 799dfc8d36946880b66f5d3a5737014735f48bc0..33b6e57ae08e98353896fbede9a5e230a388a298 100644 --- a/kernel/unistd.h +++ b/kernel/unistd.h @@ -13,4 +13,22 @@ #define __NR_putstring 1 +#define __NR_open 2 +#define __NR_close 3 +#define __NR_read 4 +#define __NR_write 5 +#define __NR_lseek 6 + +#define __NR_fork 7 +#define __NR_vfork 8 +#define __NR_execve 9 +#define __NR_exit 10 +#define __NR_wait4 11 + +#define __NR_brk 12 +#define __NR_reboot 13 + +#define __NR_chdir 14 +#define __NR_getdents 15 + #endif diff --git a/kernel/waitqueue.c b/kernel/waitqueue.c new file mode 100644 index 0000000000000000000000000000000000000000..c52134365a3ed9c74d303226ef5f78f54008dbad --- /dev/null +++ b/kernel/waitqueue.c @@ -0,0 +1,56 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#include "waitqueue.h" +#include "task.h" +#include "lib.h" + +void wait_queue_init(wait_queue_T * wait_queue,struct task_struct *tsk) +{ + list_init(&wait_queue->wait_list); + wait_queue->tsk = tsk; +} + +void sleep_on(wait_queue_T * wait_queue_head) +{ + wait_queue_T wait; + wait_queue_init(&wait,current); + current->state = TASK_UNINTERRUPTIBLE; + list_add_to_before(&wait_queue_head->wait_list,&wait.wait_list); + + schedule(); +} + +void interruptible_sleep_on(wait_queue_T *wait_queue_head) +{ + wait_queue_T wait; + wait_queue_init(&wait,current); + current->state = TASK_INTERRUPTIBLE; + list_add_to_before(&wait_queue_head->wait_list,&wait.wait_list); + + schedule(); +} + +void wakeup(wait_queue_T * wait_queue_head,long state) +{ + wait_queue_T * wait = NULL; + + if(list_is_empty(&wait_queue_head->wait_list)) + return; + + wait = container_of(list_next(&wait_queue_head->wait_list),wait_queue_T,wait_list); + + if(wait->tsk->state & state) + { + list_del(&wait->wait_list); + wakeup_process(wait->tsk); + } +} + + diff --git a/kernel/waitqueue.h b/kernel/waitqueue.h new file mode 100644 index 0000000000000000000000000000000000000000..c082a409d0fcfbbfe762b484e106e125b613dcad --- /dev/null +++ b/kernel/waitqueue.h @@ -0,0 +1,30 @@ +/*************************************************** +* Copyright (c) 2018 MINE 田宇 +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of version 2 of the GNU General Public +* License as published by the Free Software Foundation. +* +***************************************************/ + +#ifndef __WAITQUEUE_H__ + +#define __WAITQUEUE_H__ + +#include "lib.h" + +typedef struct +{ + struct List wait_list; + struct task_struct *tsk; +} wait_queue_T; + +void wait_queue_init(wait_queue_T * wait_queue,struct task_struct *tsk); + +void sleep_on(wait_queue_T * wait_queue_head); + +void interruptible_sleep_on(wait_queue_T *wait_queue_head); + +void wakeup(wait_queue_T * wait_queue_head,long state); + +#endif