📄 protect.c
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/kernel/protect.c
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
07700 /* This file contains code for initialization of protected mode, to initialize
07701 * code and data segment descriptors, and to initialize global descriptors
07702 * for local descriptors in the process table.
07703 */
07704
07705 #include "kernel.h"
07706 #include "proc.h"
07707 #include "protect.h"
07708
07709 #define INT_GATE_TYPE (INT_286_GATE | DESC_386_BIT)
07710 #define TSS_TYPE (AVL_286_TSS | DESC_386_BIT)
07711
07712 struct desctableptr_s {
07713 char limit[sizeof(u16_t)];
07714 char base[sizeof(u32_t)]; /* really u24_t + pad for 286 */
07715 };
07716
07717 struct gatedesc_s {
07718 u16_t offset_low;
07719 u16_t selector;
07720 u8_t pad; /* |000|XXXXX| ig & trpg, |XXXXXXXX| task g */
07721 u8_t p_dpl_type; /* |P|DL|0|TYPE| */
07722 u16_t offset_high;
07723 };
07724
07725 struct tss_s {
07726 reg_t backlink;
07727 reg_t sp0; /* stack pointer to use during interrupt */
07728 reg_t ss0; /* " segment " " " " */
07729 reg_t sp1;
07730 reg_t ss1;
07731 reg_t sp2;
07732 reg_t ss2;
07733 reg_t cr3;
07734 reg_t ip;
07735 reg_t flags;
07736 reg_t ax;
07737 reg_t cx;
07738 reg_t dx;
07739 reg_t bx;
07740 reg_t sp;
07741 reg_t bp;
07742 reg_t si;
07743 reg_t di;
07744 reg_t es;
07745 reg_t cs;
07746 reg_t ss;
07747 reg_t ds;
07748 reg_t fs;
07749 reg_t gs;
07750 reg_t ldt;
07751 u16_t trap;
07752 u16_t iobase;
07753 };
07754
07755 PUBLIC struct segdesc_s gdt[GDT_SIZE];
07756 PRIVATE struct gatedesc_s idt[IDT_SIZE]; /* zero-init so none present */
07757 PUBLIC struct tss_s tss; /* zero init */
07758
07759 FORWARD _PROTOTYPE( void int_gate, (unsigned vec_nr, phys_bytes base,
07760 unsigned dpl_type) );
07761 FORWARD _PROTOTYPE( void sdesc, (struct segdesc_s *segdp, phys_bytes base,
07762 phys_bytes size) );
07763
07764 /*=========================================================================*
07765 * prot_init *
07766 *=========================================================================*/
07767 PUBLIC void prot_init()
07768 {
07769 /* Set up tables for protected mode.
07770 * All GDT slots are allocated at compile time.
07771 */
07772
07773 phys_bytes code_bytes;
07774 phys_bytes data_bytes;
07775 struct gate_table_s *gtp;
07776 struct desctableptr_s *dtp;
07777 unsigned ldt_selector;
07778 register struct proc *rp;
07779
07780 static struct gate_table_s {
07781 _PROTOTYPE( void (*gate), (void) );
07782 unsigned char vec_nr;
07783 unsigned char privilege;
07784 }
07785 gate_table[] = {
07786 divide_error, DIVIDE_VECTOR, INTR_PRIVILEGE,
07787 single_step_exception, DEBUG_VECTOR, INTR_PRIVILEGE,
07788 nmi, NMI_VECTOR, INTR_PRIVILEGE,
07789 breakpoint_exception, BREAKPOINT_VECTOR, USER_PRIVILEGE,
07790 overflow, OVERFLOW_VECTOR, USER_PRIVILEGE,
07791 bounds_check, BOUNDS_VECTOR, INTR_PRIVILEGE,
07792 inval_opcode, INVAL_OP_VECTOR, INTR_PRIVILEGE,
07793 copr_not_available, COPROC_NOT_VECTOR, INTR_PRIVILEGE,
07794 double_fault, DOUBLE_FAULT_VECTOR, INTR_PRIVILEGE,
07795 copr_seg_overrun, COPROC_SEG_VECTOR, INTR_PRIVILEGE,
07796 inval_tss, INVAL_TSS_VECTOR, INTR_PRIVILEGE,
07797 segment_not_present, SEG_NOT_VECTOR, INTR_PRIVILEGE,
07798 stack_exception, STACK_FAULT_VECTOR, INTR_PRIVILEGE,
07799 general_protection, PROTECTION_VECTOR, INTR_PRIVILEGE,
07800 page_fault, PAGE_FAULT_VECTOR, INTR_PRIVILEGE,
07801 copr_error, COPROC_ERR_VECTOR, INTR_PRIVILEGE,
07802 { hwint00, VECTOR( 0), INTR_PRIVILEGE },
07803 { hwint01, VECTOR( 1), INTR_PRIVILEGE },
07804 { hwint02, VECTOR( 2), INTR_PRIVILEGE },
07805 { hwint03, VECTOR( 3), INTR_PRIVILEGE },
07806 { hwint04, VECTOR( 4), INTR_PRIVILEGE },
07807 { hwint05, VECTOR( 5), INTR_PRIVILEGE },
07808 { hwint06, VECTOR( 6), INTR_PRIVILEGE },
07809 { hwint07, VECTOR( 7), INTR_PRIVILEGE },
07810 { hwint08, VECTOR( 8), INTR_PRIVILEGE },
07811 { hwint09, VECTOR( 9), INTR_PRIVILEGE },
07812 { hwint10, VECTOR(10), INTR_PRIVILEGE },
07813 { hwint11, VECTOR(11), INTR_PRIVILEGE },
07814 { hwint12, VECTOR(12), INTR_PRIVILEGE },
07815 { hwint13, VECTOR(13), INTR_PRIVILEGE },
07816 { hwint14, VECTOR(14), INTR_PRIVILEGE },
07817 { hwint15, VECTOR(15), INTR_PRIVILEGE },
07818 };
07819
07820 /* This is called early and can't use tables set up by main(). */
07821 data_bytes = (phys_bytes) sizes[1] << CLICK_SHIFT;
07822 if (sizes[0] == 0)
07823 code_bytes = data_bytes; /* common I&D */
07824 else
07825 code_bytes = (phys_bytes) sizes[0] << CLICK_SHIFT;
07826
07827 /* Build gdt and idt pointers in GDT where the BIOS expects them. */
07828 dtp= (struct desctableptr_s *) &gdt[GDT_INDEX];
07829 * (u16_t *) dtp->limit = (sizeof gdt) - 1;
07830 * (u32_t *) dtp->base = vir2phys(gdt);
07831
07832 dtp= (struct desctableptr_s *) &gdt[IDT_INDEX];
07833 * (u16_t *) dtp->limit = (sizeof idt) - 1;
07834 * (u32_t *) dtp->base = vir2phys(idt);
07835
07836 /* Build segment descriptors for tasks and interrupt handlers. */
07837 init_codeseg(&gdt[CS_INDEX], code_base, code_bytes, INTR_PRIVILEGE);
07838 init_dataseg(&gdt[DS_INDEX], data_base, data_bytes, INTR_PRIVILEGE);
07839 init_dataseg(&gdt[ES_INDEX], 0L, 0L, TASK_PRIVILEGE);
07840
07841 /* Build scratch descriptors for functions in klib88. */
07842 init_dataseg(&gdt[DS_286_INDEX], (phys_bytes) 0,
07843 (phys_bytes) MAX_286_SEG_SIZE, TASK_PRIVILEGE);
07844 init_dataseg(&gdt[ES_286_INDEX], (phys_bytes) 0,
07845 (phys_bytes) MAX_286_SEG_SIZE, TASK_PRIVILEGE);
07846
07847 /* Build local descriptors in GDT for LDT's in process table.
07848 * The LDT's are allocated at compile time in the process table, and
07849 * initialized whenever a process' map is initialized or changed.
07850 */
07851 for (rp = BEG_PROC_ADDR, ldt_selector = FIRST_LDT_INDEX * DESC_SIZE;
07852 rp < END_PROC_ADDR; ++rp, ldt_selector += DESC_SIZE) {
07853 init_dataseg(&gdt[ldt_selector / DESC_SIZE], vir2phys(rp->p_ldt),
07854 (phys_bytes) sizeof rp->p_ldt, INTR_PRIVILEGE);
07855 gdt[ldt_selector / DESC_SIZE].access = PRESENT | LDT;
07856 rp->p_ldt_sel = ldt_selector;
07857 }
07858
07859 /* Build main TSS.
07860 * This is used only to record the stack pointer to be used after an
07861 * interrupt.
07862 * The pointer is set up so that an interrupt automatically saves the
07863 * current process's registers ip:cs:f:sp:ss in the correct slots in the
07864 * process table.
07865 */
07866 tss.ss0 = DS_SELECTOR;
07867 init_dataseg(&gdt[TSS_INDEX], vir2phys(&tss), (phys_bytes) sizeof tss,
07868 INTR_PRIVILEGE);
07869 gdt[TSS_INDEX].access = PRESENT | (INTR_PRIVILEGE << DPL_SHIFT) | TSS_TYPE;
07870 tss.iobase = sizeof tss; /* empty i/o permissions map */
07871
07872 /* Build descriptors for interrupt gates in IDT. */
07873 for (gtp = &gate_table[0];
07874 gtp < &gate_table[sizeof gate_table / sizeof gate_table[0]]; ++gtp) {
07875 int_gate(gtp->vec_nr, (phys_bytes) (vir_bytes) gtp->gate,
07876 PRESENT | INT_GATE_TYPE | (gtp->privilege << DPL_SHIFT));
07877 }
07878 int_gate(SYS_VECTOR, (phys_bytes) (vir_bytes) p_s_call,
07879 PRESENT | (USER_PRIVILEGE << DPL_SHIFT) | INT_GATE_TYPE);
07880 int_gate(LEVEL0_VECTOR, (phys_bytes) (vir_bytes) level0_call,
07881 PRESENT | (TASK_PRIVILEGE << DPL_SHIFT) | INT_GATE_TYPE);
07882 int_gate(SYS386_VECTOR, (phys_bytes) (vir_bytes) s_call,
07883 PRESENT | (USER_PRIVILEGE << DPL_SHIFT) | INT_GATE_TYPE);
07884 }
07886 /*=========================================================================*
07887 * init_codeseg *
07888 *=========================================================================*/
07889 PUBLIC void init_codeseg(segdp, base, size, privilege)
07890 register struct segdesc_s *segdp;
07891 phys_bytes base;
07892 phys_bytes size;
07893 int privilege;
07894 {
07895 /* Build descriptor for a code segment. */
07896
07897 sdesc(segdp, base, size);
07898 segdp->access = (privilege << DPL_SHIFT)
07899 | (PRESENT | SEGMENT | EXECUTABLE | READABLE);
07900 /* CONFORMING = 0, ACCESSED = 0 */
07901 }
07903 /*=========================================================================*
07904 * init_dataseg *
07905 *=========================================================================*/
07906 PUBLIC void init_dataseg(segdp, base, size, privilege)
07907 register struct segdesc_s *segdp;
07908 phys_bytes base;
07909 phys_bytes size;
07910 int privilege;
07911 {
07912 /* Build descriptor for a data segment. */
07913
07914 sdesc(segdp, base, size);
07915 segdp->access = (privilege << DPL_SHIFT) | (PRESENT | SEGMENT | WRITEABLE);
07916 /* EXECUTABLE = 0, EXPAND_DOWN = 0, ACCESSED = 0 */
07917 }
07919 /*=========================================================================*
07920 * sdesc *
07921 *=========================================================================*/
07922 PRIVATE void sdesc(segdp, base, size)
07923 register struct segdesc_s *segdp;
07924 phys_bytes base;
07925 phys_bytes size;
07926 {
07927 /* Fill in the size fields (base, limit and granularity) of a descriptor. */
07928
07929 segdp->base_low = base;
07930 segdp->base_middle = base >> BASE_MIDDLE_SHIFT;
07931 segdp->base_high = base >> BASE_HIGH_SHIFT;
07932 --size; /* convert to a limit, 0 size means 4G */
07933 if (size > BYTE_GRAN_MAX) {
07934 segdp->limit_low = size >> PAGE_GRAN_SHIFT;
07935 segdp->granularity = GRANULAR | (size >>
07936 (PAGE_GRAN_SHIFT + GRANULARITY_SHIFT));
07937 } else {
07938 segdp->limit_low = size;
07939 segdp->granularity = size >> GRANULARITY_SHIFT;
07940 }
07941 segdp->granularity |= DEFAULT; /* means BIG for data seg */
07942 }
07944 /*=========================================================================*
07945 * seg2phys *
07946 *=========================================================================*/
07947 PUBLIC phys_bytes seg2phys(seg)
07948 U16_t seg;
07949 {
07950 /* Return the base address of a segment, with seg being either a 8086 segment
07951 * register, or a 286/386 segment selector.
07952 */
07953 phys_bytes base;
07954 struct segdesc_s *segdp;
07955
07956 if (!protected_mode) {
07957 base = hclick_to_physb(seg);
07958 } else {
07959 segdp = &gdt[seg >> 3];
07960 base = segdp->base_low | ((u32_t) segdp->base_middle << 16);
07961 base |= ((u32_t) segdp->base_high << 24);
07962 }
07963 return base;
07964 }
07966 /*=========================================================================*
07967 * int_gate *
07968 *=========================================================================*/
07969 PRIVATE void int_gate(vec_nr, base, dpl_type)
07970 unsigned vec_nr;
07971 phys_bytes base;
07972 unsigned dpl_type;
07973 {
07974 /* Build descriptor for an interrupt gate. */
07975
07976 register struct gatedesc_s *idp;
07977
07978 idp = &idt[vec_nr];
07979 idp->offset_low = base;
07980 idp->selector = CS_SELECTOR;
07981 idp->p_dpl_type = dpl_type;
07982 idp->offset_high = base >> OFFSET_HIGH_SHIFT;
07983 }
07985 /*=========================================================================*
07986 * enable_iop *
07987 *=========================================================================*/
07988 PUBLIC void enable_iop(pp)
07989 struct proc *pp;
07990 {
07991 /* Allow a user process to use I/O instructions. Change the I/O Permission
07992 * Level bits in the psw. These specify least-privileged Current Permission
07993 * Level allowed to execute I/O instructions. Users and servers have CPL 3.
07994 * You can't have less privilege than that. Kernel has CPL 0, tasks CPL 1.
07995 */
07996 pp->p_reg.psw |= 0x3000;
07997 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -