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

📄 protect.c

📁 一个简单的操作系统minix的核心代码
💻 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 + -