CS318 - Pintos
Pintos source browser for JHU CS318 course
Enumerations | Functions | Variables
gdt.c File Reference
#include "userprog/gdt.h"
#include <debug.h>
#include "userprog/tss.h"
#include "threads/palloc.h"
#include "threads/vaddr.h"
Include dependency graph for gdt.c:

Go to the source code of this file.

Enumerations

enum  seg_class { CLS_SYSTEM = 0, CLS_CODE_DATA = 1 }
 System segment or code/data segment? More...
 
enum  seg_granularity { GRAN_BYTE = 0, GRAN_PAGE = 1 }
 Limit has byte or 4 kB page granularity? More...
 

Functions

static uint64_t make_code_desc (int dpl)
 GDT helpers. More...
 
static uint64_t make_data_desc (int dpl)
 Returns a descriptor for a writable data segment with base at 0, a limit of 4 GB, and the given DPL. More...
 
static uint64_t make_tss_desc (void *laddr)
 Returns a descriptor for an "available" 32-bit Task-State Segment with its base at the given linear address, a limit of 0x67 bytes (the size of a 32-bit TSS), and a DPL of 0. More...
 
static uint64_t make_gdtr_operand (uint16_t limit, void *base)
 Returns a descriptor that yields the given LIMIT and BASE when used as an operand for the LGDT instruction. More...
 
void gdt_init (void)
 Sets up a proper GDT. More...
 
static uint64_t make_seg_desc (uint32_t base, uint32_t limit, enum seg_class class, int type, int dpl, enum seg_granularity granularity)
 Returns a segment descriptor with the given 32-bit BASE and 20-bit LIMIT (whose interpretation depends on GRANULARITY). More...
 

Variables

static uint64_t gdt [SEL_CNT]
 The Global Descriptor Table (GDT). More...
 

Enumeration Type Documentation

◆ seg_class

enum seg_class

System segment or code/data segment?

Enumerator
CLS_SYSTEM 

System segment.

CLS_CODE_DATA 

Code or data segment.

Definition at line 57 of file gdt.c.

◆ seg_granularity

Limit has byte or 4 kB page granularity?

Enumerator
GRAN_BYTE 

Limit has 1-byte granularity.

GRAN_PAGE 

Limit has 4 kB granularity.

Definition at line 64 of file gdt.c.

Function Documentation

◆ gdt_init()

void gdt_init ( void  )

Sets up a proper GDT.

userprog/gdt.h

The bootstrap loader's GDT didn't include user-mode selectors or a TSS, but we need both now.

Definition at line 36 of file gdt.c.

References gdt, make_code_desc(), make_data_desc(), make_gdtr_operand(), make_tss_desc(), SEL_KCSEG, SEL_KDSEG, SEL_NULL, SEL_TSS, SEL_UCSEG, SEL_UDSEG, and tss_get().

Referenced by pintos_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ make_code_desc()

static uint64_t make_code_desc ( int  dpl)
static

GDT helpers.

Returns a descriptor for a readable code segment with base at 0, a limit of 4 GB, and the given DPL.

Definition at line 116 of file gdt.c.

References CLS_CODE_DATA, GRAN_PAGE, and make_seg_desc().

Referenced by gdt_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ make_data_desc()

static uint64_t make_data_desc ( int  dpl)
static

Returns a descriptor for a writable data segment with base at 0, a limit of 4 GB, and the given DPL.

Definition at line 124 of file gdt.c.

References CLS_CODE_DATA, GRAN_PAGE, and make_seg_desc().

Referenced by gdt_init().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ make_gdtr_operand()

static uint64_t make_gdtr_operand ( uint16_t  limit,
void *  base 
)
static

Returns a descriptor that yields the given LIMIT and BASE when used as an operand for the LGDT instruction.

Definition at line 143 of file gdt.c.

Referenced by gdt_init().

Here is the caller graph for this function:

◆ make_seg_desc()

static uint64_t make_seg_desc ( uint32_t  base,
uint32_t  limit,
enum seg_class  class,
int  type,
int  dpl,
enum seg_granularity  granularity 
)
static

Returns a segment descriptor with the given 32-bit BASE and 20-bit LIMIT (whose interpretation depends on GRANULARITY).

The descriptor represents a system or code/data segment according to CLASS, and TYPE is its type (whose interpretation depends on the class).

The segment has descriptor privilege level DPL, meaning that it can be used in rings numbered DPL or lower. In practice, DPL==3 means that user processes can use the segment and DPL==0 means that only the kernel can use the segment. See [IA32-v3a] 4.5 "Privilege Levels" for further discussion.

< Limit 15:0.

< Base 15:0.

< Base 23:16.

< Segment type.

< 0=system, 1=code/data.

< Descriptor privilege.

< Present.

< Limit 16:19.

< 32-bit segment.

< Byte/page granularity.

< Base 31:24.

Definition at line 82 of file gdt.c.

References ASSERT, CLS_CODE_DATA, CLS_SYSTEM, GRAN_BYTE, and GRAN_PAGE.

Referenced by make_code_desc(), make_data_desc(), and make_tss_desc().

Here is the caller graph for this function:

◆ make_tss_desc()

static uint64_t make_tss_desc ( void *  laddr)
static

Returns a descriptor for an "available" 32-bit Task-State Segment with its base at the given linear address, a limit of 0x67 bytes (the size of a 32-bit TSS), and a DPL of 0.

See [IA32-v3a] 6.2.2 "TSS Descriptor".

Definition at line 134 of file gdt.c.

References CLS_SYSTEM, GRAN_BYTE, and make_seg_desc().

Referenced by gdt_init().

Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ gdt

uint64_t gdt[SEL_CNT]
static

The Global Descriptor Table (GDT).

The GDT, an x86-specific structure, defines segments that can potentially be used by all processes in a system, subject to their permissions. There is also a per-process Local Descriptor Table (LDT) but that is not used by modern operating systems.

Each entry in the GDT, which is known by its byte offset in the table, identifies a segment. For our purposes only three types of segments are of interest: code, data, and TSS or Task-State Segment descriptors. The former two types are exactly what they sound like. The TSS is used primarily for stack switching on interrupts.

For more information on the GDT as used here, refer to [IA32-v3a] 3.2 "Using Segments" through 3.5 "System Descriptor Types".

Definition at line 25 of file gdt.c.

Referenced by gdt_init().