learningOS开源操作系统社区
  • 首页
  • 训练营
  • 明星学员
  • 共建单位
  • 项目实习
  • 问答论坛
登录
    Copyright © 2024 opencamp.ai All rights reserved.
    有关于mm/pmm.c中GDT表的建立
    匿名2023/07/31 19:52:03提问
      特权级lab1student
    367

    在Lab1的实验中需要了解GDT表的建立,于是我在mm/pmm.c文件中找到了如下的定义:

    /* *
     * Global Descriptor Table:
     *
     * The kernel and user segments are identical (except for the DPL). To load
     * the %ss register, the CPL must equal the DPL. Thus, we must duplicate the
     * segments for the user and the kernel. Defined as follows:
     *   - 0x0 :  unused (always faults -- for trapping NULL far pointers)
     *   - 0x8 :  kernel code segment
     *   - 0x10:  kernel data segment
     *   - 0x18:  user code segment
     *   - 0x20:  user data segment
     *   - 0x28:  defined for tss, initialized in gdt_init
     * */
    static struct segdesc gdt[] = {
        SEG_NULL,
        [SEG_KTEXT] = SEG(STA_X | STA_R, 0x0, 0xFFFFFFFF, DPL_KERNEL),
        [SEG_KDATA] = SEG(STA_W, 0x0, 0xFFFFFFFF, DPL_KERNEL),
        [SEG_UTEXT] = SEG(STA_X | STA_R, 0x0, 0xFFFFFFFF, DPL_USER),
        [SEG_UDATA] = SEG(STA_W, 0x0, 0xFFFFFFFF, DPL_USER),
        [SEG_TSS]    = SEG_NULL,
    };

    老师在课堂和MOOC中均提到,uCore将x86提供的段机制看作是直接映射,在页机制未启用的前提下,达到了逻辑地址=线性地址=物理地址的效果。观察上面的代码,除了第一个SEG_NULL是硬件需要之外,其他的五个SEG有四个都将地址映射到了0x00000000-0xFFFFFFFF,也就是说:当访存的逻辑地址唯一确定的时候,对应的线性地址就确定了,而对该逻辑地址的权限则由CS或是DS等寄存器决定,因此也可以通过观察CS的值确定当前到底是用户态还是内核态。

    那么为什么还需要这6个段呢?在课下与陈老师的讨论中,得知这样做的目的是权限控制。

    举个例子,当CS为用户态时,如果试图执行某些特权指令或是内核态中断,就会触发x86的13号一般保护异常(  http://ilinuxkernel.com/?p=1388 )。 在lab1的challenge实验中,建立IDT表的时候,需要把T_SWITCH_TOK特权级别设置为DPL_USER,这样一来,在用户态执行lab1_switch_to_kernel的int指令时,就不会触发一般保护异常了。

    至于SEG_NULL和SEG_TSS,前者应该是x86硬件需求,后者是之后的lab中会用到的用户用户态和内核态栈切换存储寄存器的临时区域,是动态建立的。

    但其实写到这里,我还是有一个不太理解的地方,那就是既然之后会有页机制来进行权限控制,为什么还要在这里重复进行检查呢,这一步是多余的吗(即段表只设置NULL和KERNEL可以吗)?

    希望同学一起讨论一下,如果我有新的理解再更新。

    回答(1)
    即可发布评论
      推荐问答
        Simple Empty
        暂无数据