CS318 - Pintos
Pintos source browser for JHU CS318 course
tss.c
Go to the documentation of this file.
1 #include "userprog/tss.h"
2 #include <debug.h>
3 #include <stddef.h>
4 #include "userprog/gdt.h"
5 #include "threads/thread.h"
6 #include "threads/palloc.h"
7 #include "threads/vaddr.h"
8 
9 /** The Task-State Segment (TSS).
10 
11  Instances of the TSS, an x86-specific structure, are used to
12  define "tasks", a form of support for multitasking built right
13  into the processor. However, for various reasons including
14  portability, speed, and flexibility, most x86 OSes almost
15  completely ignore the TSS. We are no exception.
16 
17  Unfortunately, there is one thing that can only be done using
18  a TSS: stack switching for interrupts that occur in user mode.
19  When an interrupt occurs in user mode (ring 3), the processor
20  consults the ss0 and esp0 members of the current TSS to
21  determine the stack to use for handling the interrupt. Thus,
22  we must create a TSS and initialize at least these fields, and
23  this is precisely what this file does.
24 
25  When an interrupt is handled by an interrupt or trap gate
26  (which applies to all interrupts we handle), an x86 processor
27  works like this:
28 
29  - If the code interrupted by the interrupt is in the same
30  ring as the interrupt handler, then no stack switch takes
31  place. This is the case for interrupts that happen when
32  we're running in the kernel. The contents of the TSS are
33  irrelevant for this case.
34 
35  - If the interrupted code is in a different ring from the
36  handler, then the processor switches to the stack
37  specified in the TSS for the new ring. This is the case
38  for interrupts that happen when we're in user space. It's
39  important that we switch to a stack that's not already in
40  use, to avoid corruption. Because we're running in user
41  space, we know that the current process's kernel stack is
42  not in use, so we can always use that. Thus, when the
43  scheduler switches threads, it also changes the TSS's
44  stack pointer to point to the new thread's kernel stack.
45  (The call is in thread_schedule_tail() in thread.c.)
46 
47  See [IA32-v3a] 6.2.1 "Task-State Segment (TSS)" for a
48  description of the TSS. See [IA32-v3a] 5.12.1 "Exception- or
49  Interrupt-Handler Procedures" for a description of when and
50  how stack switching occurs during an interrupt. */
51 struct tss
52  {
54  void *esp0; /**< Ring 0 stack virtual address. */
55  uint16_t ss0, :16; /**< Ring 0 stack segment selector. */
56  void *esp1;
57  uint16_t ss1, :16;
58  void *esp2;
59  uint16_t ss2, :16;
60  uint32_t cr3;
61  void (*eip) (void);
65  uint16_t es, :16;
66  uint16_t cs, :16;
67  uint16_t ss, :16;
68  uint16_t ds, :16;
69  uint16_t fs, :16;
70  uint16_t gs, :16;
71  uint16_t ldt, :16;
73  };
74 
75 /** Kernel TSS. */
76 static struct tss *tss;
77 
78 /** Initializes the kernel TSS. */
79 void
80 tss_init (void)
81 {
82  /* Our TSS is never used in a call gate or task gate, so only a
83  few fields of it are ever referenced, and those are the only
84  ones we initialize. */
86  tss->ss0 = SEL_KDSEG;
87  tss->bitmap = 0xdfff;
88  tss_update ();
89 }
90 
91 /** Returns the kernel TSS. */
92 struct tss *
93 tss_get (void)
94 {
95  ASSERT (tss != NULL);
96  return tss;
97 }
98 
99 /** Sets the ring 0 stack pointer in the TSS to point to the end
100  of the thread stack. */
101 void
102 tss_update (void)
103 {
104  ASSERT (tss != NULL);
105  tss->esp0 = (uint8_t *) thread_current () + PGSIZE;
106 }
uint8_t
unsigned char uint8_t
Definition: stdint.h:20
tss::bitmap
uint16_t uint16_t uint16_t uint16_t uint16_t uint16_t uint16_t uint16_t bitmap
Definition: tss.c:65
gdt.h
tss::ds
uint16_t uint16_t uint16_t uint16_t ds
Definition: tss.c:65
PAL_ZERO
Zero page contents.
Definition: palloc.h:10
tss::edx
uint32_t edx
Definition: tss.c:63
NULL
#define NULL
Definition: stddef.h:4
tss::ss
uint16_t uint16_t uint16_t ss
Definition: tss.c:65
uint16_t
unsigned short int uint16_t
Definition: stdint.h:23
tss::eax
uint32_t eax
Definition: tss.c:63
thread_current
struct thread * thread_current(void)
Returns the running thread.
Definition: thread.c:256
PGSIZE
#define PGSIZE
Bytes in a page.
Definition: vaddr.h:20
tss
The Task-State Segment (TSS).
Definition: tss.c:51
tss::esp0
uint16_t void * esp0
Ring 0 stack virtual address.
Definition: tss.c:53
tss::ss1
uint16_t ss1
Definition: tss.c:57
palloc_get_page
void * palloc_get_page(enum palloc_flags flags)
Obtains a single free page and returns its kernel virtual address.
Definition: palloc.c:111
tss::ecx
uint32_t ecx
Definition: tss.c:63
PAL_ASSERT
Panic on failure.
Definition: palloc.h:9
tss::edi
uint32_t edi
Definition: tss.c:64
tss::esp
uint32_t esp
Definition: tss.c:64
uint32_t
unsigned int uint32_t
Definition: stdint.h:26
tss::fs
uint16_t uint16_t uint16_t uint16_t uint16_t fs
Definition: tss.c:65
tss::ldt
uint16_t uint16_t uint16_t uint16_t uint16_t uint16_t uint16_t ldt
Definition: tss.c:65
tss::cs
uint16_t uint16_t cs
Definition: tss.c:65
tss::cr3
uint16_t uint32_t cr3
Definition: tss.c:59
palloc.h
tss::es
uint16_t es
Definition: tss.c:65
ASSERT
#define ASSERT(CONDITION)
This is outside the header guard so that debug.h may be included multiple times with different settin...
Definition: debug.h:31
tss::esp2
uint16_t void * esp2
Definition: tss.c:57
tss::ebx
uint32_t ebx
Definition: tss.c:63
tss::back_link
uint16_t back_link
Definition: tss.c:53
tss::ebp
uint32_t ebp
Definition: tss.c:64
tss::ss2
uint16_t ss2
Definition: tss.c:59
tss::esp1
uint16_t void * esp1
Ring 0 stack segment selector.
Definition: tss.c:55
tss::eflags
uint32_t eflags
Definition: tss.c:62
tss_init
void tss_init(void)
Initializes the kernel TSS.
Definition: tss.c:80
tss::esi
uint32_t esi
Definition: tss.c:64
vaddr.h
SEL_KDSEG
#define SEL_KDSEG
Kernel data selector.
Definition: loader.h:31
tss::gs
uint16_t uint16_t uint16_t uint16_t uint16_t uint16_t gs
Definition: tss.c:65
tss::eip
void(* eip)(void)
Definition: tss.c:61
tss_update
void tss_update(void)
Sets the ring 0 stack pointer in the TSS to point to the end of the thread stack.
Definition: tss.c:102
thread.h
stddef.h
tss.h
tss_get
struct tss * tss_get(void)
Returns the kernel TSS.
Definition: tss.c:93
tss
static struct tss * tss
Kernel TSS.
Definition: tss.c:76
tss::ss0
uint16_t ss0
Definition: tss.c:55
debug.h
tss::trace
uint16_t uint16_t uint16_t uint16_t uint16_t uint16_t uint16_t uint16_t trace
Definition: tss.c:65