1 00:00:00,690 --> 00:00:07,950 In this lecture, we will talk about Task state segment, TSS and enable interrupts in user mode. 2 00:00:07,950 --> 00:00:10,530 When we are running in ring3, an interrupt is fired 3 00:00:11,190 --> 00:00:16,350 the control will be transferred to the interrupt handler which runs in ring0 in our system. 4 00:00:16,920 --> 00:00:22,830 Remember the DPL of the segment descriptor which the interrupt handler is at is set to 0. 5 00:00:23,820 --> 00:00:31,740 In this process, the ss segment register is also loaded with null descriptor by the processor. 6 00:00:31,740 --> 00:00:34,500 and rsp register is also loaded with a new value. 7 00:00:35,220 --> 00:00:38,570 The value of RSP is stored in the TSS. 8 00:00:39,670 --> 00:00:46,930 Therefore, what we need to do is set up the TSS and specify the new value of RSP in the TSS. 9 00:00:47,620 --> 00:00:50,260 as you see, this is a structure of tss. 10 00:00:50,800 --> 00:00:53,710 The field of RSP0 is what we want. 11 00:00:54,830 --> 00:01:03,020 When the control transferred from low privilege level to ring0, the value of RSP0 is loaded into RSP register. 12 00:01:03,990 --> 00:01:10,140 Since we don’t use ring1 and ring2, we are not gonna set those fields. The interrupt stack table, 13 00:01:10,140 --> 00:01:13,710 as we saw in the interrupt descriptor, 14 00:01:14,310 --> 00:01:21,120 if the IST field in the interrupt descriptor is non-zero, then it is the index of IST here. 15 00:01:21,400 --> 00:01:28,740 For example, if it is 1, then the value of IST1 is loaded in RSP instead of RSP0 value. 16 00:01:28,740 --> 00:01:29,130 . 17 00:01:29,730 --> 00:01:35,940 Since we have set the interrupt descriptors with IST field being 0, we are not gonna use the IST fields here. 18 00:01:35,940 --> 00:01:36,870 . 19 00:01:37,470 --> 00:01:45,300 The last item is the address of io permission bitmap which is used for protection for io port addresses. 20 00:01:45,900 --> 00:01:47,850 It is not used in our system. 21 00:01:52,050 --> 00:01:59,710 The TSS descriptor is stored in the GDT. Unlike the code segment and data segment descriptors where the base and limit are ignored, 22 00:01:59,730 --> 00:02:06,630 the base and limit attributes in TSS descriptor are used. 23 00:02:07,140 --> 00:02:14,010 So when we set up the descriptor, the base address and limit need to be set correctly. 24 00:02:14,190 --> 00:02:20,520 the value 0,1,0,0,1 means that this is the 64-bit TSS descriptor. 25 00:02:21,540 --> 00:02:26,370 The meaning of P and DPL is the same as in the code and data segment descriptors. 26 00:02:28,120 --> 00:02:34,690 The G and available bit are not used in our system, so this part of the attribute will be set to 0. 27 00:02:34,690 --> 00:02:39,340 In the upper part of the descriptor, we have 5 0s, 28 00:02:39,850 --> 00:02:42,640 and the part in grey means it is reserved. 29 00:02:43,420 --> 00:02:46,460 Right now, we have seen the tss descriptor. 30 00:02:46,990 --> 00:02:49,960 we also need a selector to reference the descriptor. 31 00:02:50,740 --> 00:02:54,550 Loading the TSS selector is different from loading the code segment selector. 32 00:02:55,000 --> 00:02:58,210 Here we load the selector using instruction load task register. 33 00:02:58,210 --> 00:03:06,100 After the selector is loaded, the processor then uses the selector to 34 00:03:06,100 --> 00:03:07,690 locate the TSS descriptor in the GDT. 35 00:03:08,230 --> 00:03:10,810 Let’s see how to implement it in the project. 36 00:03:14,430 --> 00:03:19,530 The first thing I’m gonna do is define the Task state segment structure. 37 00:03:25,720 --> 00:03:27,520 We call it TSS. 38 00:03:28,870 --> 00:03:32,650 As we saw in the slide, the first four bytes are reserved, 39 00:03:33,490 --> 00:03:34,960 so we assign 0 to it. 40 00:03:38,310 --> 00:03:40,380 The next field is RSP0, 41 00:03:40,560 --> 00:03:44,700 this is the field we need to set with the new address of RSP. 42 00:03:45,930 --> 00:03:48,150 Here we want the RSP loaded with 43 00:03:50,710 --> 00:03:58,760 150000 when the interrupt handler is called. Other fields are not used in the system, we simply set them to 0. 44 00:03:58,760 --> 00:03:59,510 . 45 00:04:01,160 --> 00:04:03,530 So we use directive times. 46 00:04:08,540 --> 00:04:15,650 The last field is the address of IO permission bitmap. We assign the size of TSS to it 47 00:04:15,650 --> 00:04:18,110 which means IO permission bitmap is not used. 48 00:04:22,120 --> 00:04:25,090 Ok, we define the length of the TSS. 49 00:04:31,570 --> 00:04:37,930 Once the Task state segment is defined, what we are gonna do next is define the TSS descriptor. 50 00:04:38,230 --> 00:04:39,460 . 51 00:04:40,450 --> 00:04:44,800 In the GDT, we add a new entry called tss descriptor 52 00:04:50,400 --> 00:04:52,270 so that we can see it easily. 53 00:04:52,680 --> 00:04:56,910 If you don’t want the label tss descriptor, you can simply remove it. 54 00:04:57,910 --> 00:05:01,720 The first two bytes are the lower 16 bits of tss limit. 55 00:05:02,750 --> 00:05:06,410 We set it to the length of TSS minus 1. 56 00:05:10,730 --> 00:05:14,120 The base address of TSS is set to 0 for the moment, 57 00:05:16,790 --> 00:05:19,370 we will assign the address in the code. 58 00:05:20,060 --> 00:05:23,140 So we set the next 3 bytes to 0s 59 00:05:25,210 --> 00:05:31,780 which is the lower 24 bits of the base address. The next byte is attribute field. We assign the value. 60 00:05:31,780 --> 00:05:32,230 . 61 00:05:34,000 --> 00:05:34,630 89 62 00:05:37,490 --> 00:05:44,270 In the binary format, you can see the present bit is 1, DPL is 0, 63 00:05:44,270 --> 00:05:48,770 and then 0,1,0,0,1 specifies this is the 64-bit TSS. 64 00:05:49,760 --> 00:05:52,400 As for other fields, simply set them to zero. 65 00:05:56,160 --> 00:05:58,650 OK, we are done. At the start of the code, 66 00:06:01,980 --> 00:06:04,050 we will load the TSS descriptor. 67 00:06:05,110 --> 00:06:09,250 First, we need to copy the address of TSS to the descriptor, 68 00:06:13,450 --> 00:06:16,080 We move rax, tss. 69 00:06:17,290 --> 00:06:22,150 The lower 16 bits of the address is in the third bytes of the tss descriptor. 70 00:06:23,170 --> 00:06:23,740 We move 71 00:06:25,440 --> 00:06:30,330 tss descriptor plus 2 and ax. 72 00:06:32,150 --> 00:06:37,340 Bit 16 to 23 of the address is in the fifth bytes of the descriptor. 73 00:06:38,290 --> 00:06:39,400 We shift right 74 00:06:39,430 --> 00:06:41,410 the value in rax by 16 bits. 75 00:06:43,890 --> 00:06:51,030 Bit 16 to 23 of the address is now in register al and then move tss descriptor 76 00:06:55,390 --> 00:06:57,310 plus 4 and al. 77 00:06:59,000 --> 00:07:01,130 Then we continue to shift right rax 78 00:07:03,200 --> 00:07:03,800 8 bits. 79 00:07:05,510 --> 00:07:10,160 The next part of the base address is in the 8th byte of the descriptor, 80 00:07:10,310 --> 00:07:11,120 so we move 81 00:07:13,250 --> 00:07:18,140 tss descriptor plus 7 and al. 82 00:07:20,250 --> 00:07:26,220 The upper 32bits of the address is in the next location. We shift rax 8bits. 83 00:07:28,740 --> 00:07:33,060 Eax holds the upper 32bits of the address now and we move 84 00:07:34,600 --> 00:07:37,190 tss descriptor plus 8, 85 00:07:38,710 --> 00:07:39,340 , 86 00:07:41,570 --> 00:07:42,030 OK. 87 00:07:42,050 --> 00:07:44,990 the tss descriptor is set at this point. 88 00:07:45,620 --> 00:07:52,450 We can load the selector using load task register instruction. The selector we use is 20 in hexadecimal, 89 00:07:52,490 --> 00:07:56,140 since the descriptor is the fifth entry in the GDT. 90 00:07:57,330 --> 00:08:02,310 we move ax, 20 and load task register, 91 00:08:04,480 --> 00:08:05,050 ax. 92 00:08:07,480 --> 00:08:08,030 All right. 93 00:08:08,050 --> 00:08:10,450 setting up the tss is finally done. 94 00:08:11,970 --> 00:08:17,840 Before we test it out, we need to enable the interrupt. When we get from ring0 to ring3, 95 00:08:17,850 --> 00:08:18,360 , 96 00:08:20,920 --> 00:08:26,140 the interrupt flag is cleared, bit 9 of rflags is the interrupt flag. 97 00:08:27,340 --> 00:08:30,430 So instead of pushing the value 2, 98 00:08:32,929 --> 00:08:40,940 we push 202, indicating that the interrupt is enabled. Once we return to user entry, 99 00:08:40,940 --> 00:08:44,390 the value will be loaded in rflags and the interrupt is enabled. 100 00:08:45,140 --> 00:08:48,170 Remember the timer is configured and working now. 101 00:08:48,710 --> 00:08:53,060 Once the timer interrupt is fired, the execution is interrupted 102 00:08:53,420 --> 00:08:57,560 and the processor responds to the interrupt, we will see the timer handler is called 103 00:08:57,590 --> 00:08:59,030 if everything goes as expected. 104 00:09:00,020 --> 00:09:01,070 So we save the file, 105 00:09:02,750 --> 00:09:03,890 and build a project. 106 00:09:11,660 --> 00:09:12,040 OK. 107 00:09:12,080 --> 00:09:19,910 As you can see we have 3 characters K, U, and T. So the character T is what we expect. 108 00:09:19,910 --> 00:09:21,080 the TSS is working.