1 /*
2  * Copyright 2014, General Dynamics C4 Systems
3  *
4  * SPDX-License-Identifier: GPL-2.0-only
5  */
6 
7 #include <config.h>
8 #include <api/syscall.h>
9 #include <machine/io.h>
10 #include <kernel/boot.h>
11 #include <model/statedata.h>
12 #include <arch/kernel/vspace.h>
13 #include <arch/kernel/boot.h>
14 #include <arch/kernel/boot_sys.h>
15 #include <arch/api/invocation.h>
16 #include <benchmark/benchmark_track.h>
17 #include <arch/kernel/tlb_bitmap.h>
18 #include <mode/kernel/tlb.h>
19 
20 /* 'gdt_idt_ptr' is declared globally because of a C-subset restriction.
21  * It is only used in init_drts(), which therefore is non-reentrant.
22  */
23 gdt_idt_ptr_t gdt_idt_ptr;
24 
25 /* initialise the Task State Segment (TSS) */
26 
init_tss(tss_t * tss)27 BOOT_CODE void init_tss(tss_t *tss)
28 {
29     *tss = tss_new(
30                sizeof(*tss),   /* io_map_base  */
31                0,              /* trap         */
32                SEL_NULL,       /* sel_ldt      */
33                SEL_NULL,       /* gs           */
34                SEL_NULL,       /* fs           */
35                SEL_NULL,       /* ds           */
36                SEL_NULL,       /* ss           */
37                SEL_NULL,       /* cs           */
38                SEL_NULL,       /* es           */
39                0,              /* edi          */
40                0,              /* esi          */
41                0,              /* ebp          */
42                0,              /* esp          */
43                0,              /* ebx          */
44                0,              /* edx          */
45                0,              /* ecx          */
46                0,              /* eax          */
47                0,              /* eflags       */
48                0,              /* eip          */
49                0,              /* cr3          */
50                SEL_NULL,       /* ss2          */
51                0,              /* esp2         */
52                SEL_NULL,       /* ss1          */
53                0,              /* esp1         */
54                SEL_DS_0,       /* ss0          */
55                0,              /* esp0         */
56                0               /* prev_task    */
57            );
58     memset(&x86KSGlobalState[CURRENT_CPU_INDEX()].x86KStss.io_map[0], 0xff,
59            sizeof(x86KSGlobalState[CURRENT_CPU_INDEX()].x86KStss.io_map));
60 }
61 /* initialise Global Descriptor Table (GDT) */
62 
init_gdt(gdt_entry_t * gdt,tss_t * tss)63 BOOT_CODE void init_gdt(gdt_entry_t *gdt, tss_t *tss)
64 {
65     uint32_t tss_addr = (uint32_t)tss;
66 
67     /* Set the NULL descriptor */
68     gdt[GDT_NULL] = gdt_entry_gdt_null_new();
69 
70     /* 4GB flat kernel code segment on ring 0 descriptor */
71     gdt[GDT_CS_0] = gdt_entry_gdt_code_new(
72                         0,      /* Base high 8 bits             */
73                         1,      /* Granularity                  */
74                         1,      /* Operation size               */
75                         0,      /* Available                    */
76                         0xf,    /* Segment limit high 4 bits    */
77                         1,      /* Present                      */
78                         0,      /* Descriptor privilege level   */
79                         1,      /* readable                     */
80                         1,      /* accessed                     */
81                         0,      /* Base middle 8 bits           */
82                         0,      /* Base low 16 bits             */
83                         0xffff  /* Segment limit low 16 bits    */
84                     );
85 
86     /* 4GB flat kernel data segment on ring 0 descriptor */
87     gdt[GDT_DS_0] = gdt_entry_gdt_data_new(
88                         0,      /* Base high 8 bits             */
89                         1,      /* Granularity                  */
90                         1,      /* Operation size               */
91                         0,      /* Available                    */
92                         0xf,    /* Segment limit high 4 bits    */
93                         1,      /* Present                      */
94                         0,      /* Descriptor privilege level   */
95                         1,      /* writable                     */
96                         1,      /* accessed                     */
97                         0,      /* Base middle 8 bits           */
98                         0,      /* Base low 16 bits             */
99                         0xffff  /* Segment limit low 16 bits    */
100                     );
101 
102     /* 4GB flat userland code segment on ring 3 descriptor */
103     gdt[GDT_CS_3] = gdt_entry_gdt_code_new(
104                         0,      /* Base high 8 bits             */
105                         1,      /* Granularity                  */
106                         1,      /* Operation size               */
107                         0,      /* Available                    */
108                         0xf,    /* Segment limit high 4 bits    */
109                         1,      /* Present                      */
110                         3,      /* Descriptor privilege level   */
111                         1,      /* readable                     */
112                         1,      /* accessed                     */
113                         0,      /* Base middle 8 bits           */
114                         0,      /* Base low 16 bits             */
115                         0xffff  /* Segment limit low 16 bits    */
116                     );
117 
118     /* 4GB flat userland data segment on ring 3 descriptor */
119     gdt[GDT_DS_3] = gdt_entry_gdt_data_new(
120                         0,      /* Base high 8 bits             */
121                         1,      /* Granularity                  */
122                         1,      /* Operation size               */
123                         0,      /* Available                    */
124                         0xf,    /* Segment limit high 4 bits    */
125                         1,      /* Present                      */
126                         3,      /* Descriptor privilege level   */
127                         1,      /* writable                     */
128                         1,      /* accessed                     */
129                         0,      /* Base middle 8 bits           */
130                         0,      /* Base low 16 bits             */
131                         0xffff  /* Segment limit low 16 bits    */
132                     );
133 
134     /* Task State Segment (TSS) descriptor */
135     gdt[GDT_TSS] = gdt_entry_gdt_tss_new(
136                        tss_addr >> 24,              /* base_high 8 bits     */
137                        0,                           /* granularity          */
138                        0,                           /* avl                  */
139                        0,                           /* limit_high 4 bits    */
140                        1,                           /* present              */
141                        0,                           /* dpl                  */
142                        0,                           /* busy                 */
143                        1,                           /* always_true          */
144                        (tss_addr >> 16) & 0xff,     /* base_mid 8 bits      */
145                        (tss_addr & 0xffff),         /* base_low 16 bits     */
146                        sizeof(tss_io_t) - 1         /* limit_low 16 bits    */
147                    );
148 
149     gdt[GDT_FS] = gdt_entry_gdt_data_new(
150                       0,      /* Base high 8 bits             */
151                       1,      /* Granularity                  */
152                       1,      /* Operation size               */
153                       0,      /* Available                    */
154                       0xf,    /* Segment limit high 4 bits    */
155                       1,      /* Present                      */
156                       3,      /* Descriptor privilege level   */
157                       1,      /* writable                     */
158                       1,      /* accessed                     */
159                       0,      /* Base middle 8 bits           */
160                       0,      /* Base low 16 bits             */
161                       0xffff  /* Segment limit low 16 bits    */
162                   );
163 
164     gdt[GDT_GS] = gdt_entry_gdt_data_new(
165                       0,      /* Base high 8 bits             */
166                       1,      /* Granularity                  */
167                       1,      /* Operation size               */
168                       0,      /* Available                    */
169                       0xf,    /* Segment limit high 4 bits    */
170                       1,      /* Present                      */
171                       3,      /* Descriptor privilege level   */
172                       1,      /* writable                     */
173                       1,      /* accessed                     */
174                       0,      /* Base middle 8 bits           */
175                       0,      /* Base low 16 bits             */
176                       0xffff  /* Segment limit low 16 bits    */
177                   );
178 }
179 
180 /* initialise the Interrupt Descriptor Table (IDT) */
181 
init_idt_entry(idt_entry_t * idt,interrupt_t interrupt,void (* handler)(void))182 BOOT_CODE void init_idt_entry(idt_entry_t *idt, interrupt_t interrupt, void(*handler)(void))
183 {
184     uint32_t handler_addr = (uint32_t)handler;
185     uint32_t dpl = 3;
186 
187     if (interrupt < int_trap_min && interrupt != int_software_break_request) {
188         dpl = 0;
189     }
190 
191     idt[interrupt] = idt_entry_interrupt_gate_new(
192                          handler_addr >> 16,   /* offset_high  */
193                          1,                    /* present      */
194                          dpl,                  /* dpl          */
195                          1,                    /* gate_size    */
196                          SEL_CS_0,             /* seg_selector */
197                          handler_addr & 0xffff /* offset_low   */
198                      );
199 }
200 
map_kernel_window(uint32_t num_ioapic,paddr_t * ioapic_paddrs,uint32_t num_drhu,paddr_t * drhu_list)201 BOOT_CODE bool_t map_kernel_window(
202     uint32_t num_ioapic,
203     paddr_t   *ioapic_paddrs,
204     uint32_t   num_drhu,
205     paddr_t   *drhu_list
206 )
207 {
208     paddr_t  phys;
209     uint32_t idx;
210     pde_t    pde;
211     pte_t    pte;
212     unsigned int UNUSED i;
213 
214     /* Mapping of PPTR_BASE (virtual address) to kernel's PADDR_BASE
215      * up to end of virtual address space except for the last large page.
216      */
217     phys = PADDR_BASE;
218     idx = PPTR_BASE >> LARGE_PAGE_BITS;
219 
220     /* PPTR_TOP differs whether CONFIG_KERNEL_LOG_BUFFER
221      * is enabled or not.
222      */
223     while (idx < (PPTR_TOP >> LARGE_PAGE_BITS)) {
224         pde = pde_pde_large_new(
225                   phys,   /* page_base_address    */
226                   0,      /* pat                  */
227                   0,      /* avl                  */
228                   1,      /* global               */
229                   0,      /* dirty                */
230                   0,      /* accessed             */
231                   0,      /* cache_disabled       */
232                   0,      /* write_through        */
233                   0,      /* super_user           */
234                   1,      /* read_write           */
235                   1       /* present              */
236               );
237         ia32KSGlobalPD[idx] = pde;
238         phys += BIT(LARGE_PAGE_BITS);
239         idx++;
240     }
241 
242     /* crosscheck whether we have mapped correctly so far */
243     assert(phys == PADDR_TOP);
244 
245 #ifdef CONFIG_KERNEL_LOG_BUFFER
246     /* Map global page table for the log buffer */
247     pde = pde_pde_pt_new(
248               kpptr_to_paddr(ia32KSGlobalLogPT), /* pt_base_address  */
249               0,                 /* avl              */
250               0,                 /* accessed         */
251               0,                 /* cache_disabled   */
252               0,                 /* write_through    */
253               0,                 /* super_user       */
254               1,                 /* read_write       */
255               1                  /* present          */
256           );
257 
258     ia32KSGlobalPD[idx] = pde;
259     phys += BIT(LARGE_PAGE_BITS);
260     assert(idx == (KS_LOG_PPTR >> LARGE_PAGE_BITS));
261     idx++;
262 #endif /* CONFIG_KERNEL_LOG_BUFFER */
263 
264 #ifdef ENABLE_SMP_SUPPORT
265     /* initialize the TLB bitmap */
266     tlb_bitmap_init(ia32KSGlobalPD);
267 
268     phys += TLBBITMAP_PD_RESERVED;
269     idx += TLBBITMAP_ROOT_ENTRIES;
270 #endif /* ENABLE_SMP_SUPPORT */
271 
272     /* map page table of last 4M of virtual address space to page directory */
273     pde = pde_pde_pt_new(
274               kpptr_to_paddr(ia32KSGlobalPT), /* pt_base_address  */
275               0,                 /* avl              */
276               0,                 /* accessed         */
277               0,                 /* cache_disabled   */
278               0,                 /* write_through    */
279               0,                 /* super_user       */
280               1,                 /* read_write       */
281               1                  /* present          */
282           );
283     ia32KSGlobalPD[idx] = pde;
284 
285     /* Start with an empty guard page preceding the stack. */
286     idx = 0;
287     pte = pte_new(
288               0,      /* page_base_address    */
289               0,      /* avl                  */
290               0,      /* global               */
291               0,      /* pat                  */
292               0,      /* dirty                */
293               0,      /* accessed             */
294               0,      /* cache_disabled       */
295               0,      /* write_through        */
296               0,      /* super_user           */
297               0,      /* read_write           */
298               0       /* present              */
299           );
300     ia32KSGlobalPT[idx] = pte;
301     idx++;
302 
303     /* null mappings up to KDEV_BASE */
304 
305     while (idx < (KDEV_BASE &MASK(LARGE_PAGE_BITS)) >> PAGE_BITS) {
306         pte = pte_new(
307                   0,      /* page_base_address    */
308                   0,      /* avl                  */
309                   0,      /* global               */
310                   0,      /* pat                  */
311                   0,      /* dirty                */
312                   0,      /* accessed             */
313                   0,      /* cache_disabled       */
314                   0,      /* write_through        */
315                   0,      /* super_user           */
316                   0,      /* read_write           */
317                   0       /* present              */
318               );
319         ia32KSGlobalPT[idx] = pte;
320         idx++;
321     }
322 
323     /* map kernel devices (devices only used by the kernel) */
324     if (!map_kernel_window_devices(ia32KSGlobalPT, num_ioapic, ioapic_paddrs, num_drhu, drhu_list)) {
325         return false;
326     }
327 
328     invalidateLocalPageStructureCache();
329     return true;
330 }
331 
332 /* Note: this function will invalidate any pointers previously returned from this function */
map_temp_boot_page(void * entry,uint32_t large_pages)333 BOOT_CODE void *map_temp_boot_page(void *entry, uint32_t large_pages)
334 {
335     void *replacement_vaddr;
336     unsigned int i;
337     unsigned int offset_in_page;
338 
339     unsigned int phys_pg_start = (unsigned int)(entry) & ~MASK(LARGE_PAGE_BITS);
340     unsigned int virt_pd_start = (PPTR_BASE >> LARGE_PAGE_BITS) - large_pages;
341     unsigned int virt_pg_start = PPTR_BASE - (large_pages << LARGE_PAGE_BITS);
342 
343     for (i = 0; i < large_pages; i++) {
344         unsigned int pg_offset = i << LARGE_PAGE_BITS; // num pages since start * page size
345 
346         *(get_boot_pd() + virt_pd_start + i) = pde_pde_large_new(
347                                                    phys_pg_start + pg_offset, /* physical address */
348                                                    0, /* pat            */
349                                                    0, /* avl            */
350                                                    1, /* global         */
351                                                    0, /* dirty          */
352                                                    0, /* accessed       */
353                                                    0, /* cache_disabled */
354                                                    0, /* write_through  */
355                                                    0, /* super_user     */
356                                                    1, /* read_write     */
357                                                    1  /* present        */
358                                                );
359         invalidateLocalTranslationSingle(virt_pg_start + pg_offset);
360     }
361 
362     // assign replacement virtual addresses page
363     offset_in_page = (unsigned int)(entry) & MASK(LARGE_PAGE_BITS);
364     replacement_vaddr = (void *)(virt_pg_start + offset_in_page);
365 
366     invalidateLocalPageStructureCache();
367 
368     return replacement_vaddr;
369 }
370 
371 /* initialise CPU's descriptor table registers (GDTR, IDTR, LDTR, TR) */
372 
init_dtrs(void)373 BOOT_CODE void init_dtrs(void)
374 {
375     /* setup the GDT pointer and limit and load into GDTR */
376     gdt_idt_ptr.limit = (sizeof(gdt_entry_t) * GDT_ENTRIES) - 1;
377     gdt_idt_ptr.base = (uint32_t)x86KSGlobalState[CURRENT_CPU_INDEX()].x86KSgdt;
378     ia32_install_gdt(&gdt_idt_ptr);
379 
380     /* setup the IDT pointer and limit and load into IDTR */
381     gdt_idt_ptr.limit = (sizeof(idt_entry_t) * (int_max + 1)) - 1;
382     gdt_idt_ptr.base = (uint32_t)x86KSGlobalState[CURRENT_CPU_INDEX()].x86KSidt;
383     ia32_install_idt(&gdt_idt_ptr);
384 
385     /* load NULL LDT selector into LDTR */
386     ia32_install_ldt(SEL_NULL);
387 
388     /* load TSS selector into Task Register (TR) */
389     ia32_install_tss(SEL_TSS);
390 }
391 
create_it_page_table_cap(cap_t vspace_cap,pptr_t pptr,vptr_t vptr,asid_t asid)392 static BOOT_CODE cap_t create_it_page_table_cap(cap_t vspace_cap, pptr_t pptr, vptr_t vptr, asid_t asid)
393 {
394     cap_t cap;
395     cap = cap_page_table_cap_new(
396               1,    /* capPTIsMapped      */
397               asid, /* capPTMappedASID    */
398               vptr, /* capPTMappedAddress */
399               pptr  /* capPTBasePtr       */
400           );
401     if (asid != asidInvalid) {
402         map_it_pt_cap(vspace_cap, cap);
403     }
404     return cap;
405 }
406 
create_it_page_directory_cap(cap_t vspace_cap,pptr_t pptr,vptr_t vptr,asid_t asid)407 static BOOT_CODE cap_t create_it_page_directory_cap(cap_t vspace_cap, pptr_t pptr, vptr_t vptr, asid_t asid)
408 {
409     cap_t cap;
410     cap = cap_page_directory_cap_new(
411               true,    /* capPDIsMapped   */
412               IT_ASID, /* capPDMappedASID */
413               vptr,    /* capPDMappedAddress */
414               pptr  /* capPDBasePtr    */
415           );
416     if (asid != asidInvalid && cap_get_capType(vspace_cap) != cap_null_cap) {
417         map_it_pd_cap(vspace_cap, cap);
418     }
419     return cap;
420 }
421 
arch_get_n_paging(v_region_t it_v_reg)422 BOOT_CODE word_t arch_get_n_paging(v_region_t it_v_reg)
423 {
424     word_t n = get_n_paging(it_v_reg, PT_INDEX_BITS + PAGE_BITS);
425 #ifdef CONFIG_IOMMU
426     n += vtd_get_n_paging(&boot_state.rmrr_list);
427 #endif
428     return n;
429 }
430 
431 /* Create an address space for the initial thread.
432  * This includes page directory and page tables */
create_it_address_space(cap_t root_cnode_cap,v_region_t it_v_reg)433 BOOT_CODE cap_t create_it_address_space(cap_t root_cnode_cap, v_region_t it_v_reg)
434 {
435     cap_t      vspace_cap;
436     vptr_t     vptr;
437     seL4_SlotPos slot_pos_before;
438     seL4_SlotPos slot_pos_after;
439 
440     slot_pos_before = ndks_boot.slot_pos_cur;
441     copyGlobalMappings((vspace_root_t *)rootserver.vspace);
442     cap_t pd_cap = create_it_page_directory_cap(cap_null_cap_new(), rootserver.vspace, 0, IT_ASID);
443     write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), seL4_CapInitThreadVSpace), pd_cap);
444     vspace_cap = pd_cap;
445 
446     /* create all PT objs and caps necessary to cover userland image */
447 
448     for (vptr = ROUND_DOWN(it_v_reg.start, PT_INDEX_BITS + PAGE_BITS);
449          vptr < it_v_reg.end;
450          vptr += BIT(PT_INDEX_BITS + PAGE_BITS)) {
451         if (!provide_cap(root_cnode_cap,
452                          create_it_page_table_cap(vspace_cap, it_alloc_paging(), vptr, IT_ASID))
453            ) {
454             return cap_null_cap_new();
455         }
456     }
457 
458     slot_pos_after = ndks_boot.slot_pos_cur;
459     ndks_boot.bi_frame->userImagePaging = (seL4_SlotRegion) {
460         slot_pos_before, slot_pos_after
461     };
462 
463     return vspace_cap;
464 }
465 
create_it_frame_cap(pptr_t pptr,vptr_t vptr,asid_t asid,bool_t use_large,vm_page_map_type_t map_type)466 static BOOT_CODE cap_t create_it_frame_cap(pptr_t pptr, vptr_t vptr, asid_t asid, bool_t use_large,
467                                            vm_page_map_type_t map_type)
468 {
469     vm_page_size_t frame_size;
470 
471     if (use_large) {
472         frame_size = X86_LargePage;
473     } else {
474         frame_size = X86_SmallPage;
475     }
476 
477     return
478         cap_frame_cap_new(
479             frame_size,                    /* capFSize           */
480             ASID_LOW(asid),                /* capFMappedASIDLow  */
481             vptr,                          /* capFMappedAddress  */
482             map_type,                      /* capFMapType        */
483             false,                         /* capFIsDevice       */
484             ASID_HIGH(asid),               /* capFMappedASIDHigh */
485             wordFromVMRights(VMReadWrite), /* capFVMRights       */
486             pptr                           /* capFBasePtr        */
487         );
488 }
489 
create_unmapped_it_frame_cap(pptr_t pptr,bool_t use_large)490 BOOT_CODE cap_t create_unmapped_it_frame_cap(pptr_t pptr, bool_t use_large)
491 {
492     return create_it_frame_cap(pptr, 0, asidInvalid, use_large, X86_MappingNone);
493 }
494 
create_mapped_it_frame_cap(cap_t vspace_cap,pptr_t pptr,vptr_t vptr,asid_t asid,bool_t use_large,bool_t executable UNUSED)495 BOOT_CODE cap_t create_mapped_it_frame_cap(cap_t vspace_cap, pptr_t pptr, vptr_t vptr, asid_t asid, bool_t use_large,
496                                            bool_t executable UNUSED)
497 {
498     cap_t cap = create_it_frame_cap(pptr, vptr, asid, use_large, X86_MappingVSpace);
499     map_it_frame_cap(vspace_cap, cap);
500     return cap;
501 }
502 
503 /* ==================== BOOT CODE FINISHES HERE ==================== */
504 
makeUserPDELargePage(paddr_t paddr,vm_attributes_t vm_attr,vm_rights_t vm_rights)505 pde_t CONST makeUserPDELargePage(paddr_t paddr, vm_attributes_t vm_attr, vm_rights_t vm_rights)
506 {
507     return pde_pde_large_new(
508                paddr,                                          /* page_base_address    */
509                vm_attributes_get_x86PATBit(vm_attr),           /* pat                  */
510                0,                                              /* avl                  */
511                0,                                              /* global               */
512                0,                                              /* dirty                */
513                0,                                              /* accessed             */
514                vm_attributes_get_x86PCDBit(vm_attr),           /* cache_disabled       */
515                vm_attributes_get_x86PWTBit(vm_attr),           /* write_through        */
516                SuperUserFromVMRights(vm_rights),               /* super_user           */
517                WritableFromVMRights(vm_rights),                /* read_write           */
518                1                                               /* present              */
519            );
520 }
521 
makeUserPDEPageTable(paddr_t paddr,vm_attributes_t vm_attr)522 pde_t CONST makeUserPDEPageTable(paddr_t paddr, vm_attributes_t vm_attr)
523 {
524     return pde_pde_pt_new(
525                paddr,                                      /* pt_base_address  */
526                0,                                          /* avl              */
527                0,                                          /* accessed         */
528                vm_attributes_get_x86PCDBit(vm_attr),       /* cache_disabled   */
529                vm_attributes_get_x86PWTBit(vm_attr),       /* write_through    */
530                1,                                          /* super_user       */
531                1,                                          /* read_write       */
532                1                                           /* present          */
533            );
534 }
535 
makeUserPDEInvalid(void)536 pde_t CONST makeUserPDEInvalid(void)
537 {
538     /* The bitfield only declares two kinds of PDE entries (page tables or large pages)
539      * and an invalid entry should really be a third type, but we can simulate it by
540      * creating an invalid (present bit 0) entry of either of the defined types */
541     return pde_pde_pt_new(
542                0,  /* pt_base_address  */
543                0,  /* avl              */
544                0,  /* accessed         */
545                0,  /* cache_disabled   */
546                0,  /* write_through    */
547                0,  /* super_user       */
548                0,  /* read_write       */
549                0   /* present          */
550            );
551 }
552 
makeUserPTE(paddr_t paddr,vm_attributes_t vm_attr,vm_rights_t vm_rights)553 pte_t CONST makeUserPTE(paddr_t paddr, vm_attributes_t vm_attr, vm_rights_t vm_rights)
554 {
555     return pte_new(
556                paddr,                                          /* page_base_address    */
557                0,                                              /* avl                  */
558                0,                                              /* global               */
559                vm_attributes_get_x86PATBit(vm_attr),           /* pat                  */
560                0,                                              /* dirty                */
561                0,                                              /* accessed             */
562                vm_attributes_get_x86PCDBit(vm_attr),           /* cache_disabled       */
563                vm_attributes_get_x86PWTBit(vm_attr),           /* write_through        */
564                SuperUserFromVMRights(vm_rights),               /* super_user           */
565                WritableFromVMRights(vm_rights),                /* read_write           */
566                1                                               /* present              */
567            );
568 }
569 
570 
makeUserPTEInvalid(void)571 pte_t CONST makeUserPTEInvalid(void)
572 {
573     return pte_new(
574                0,                   /* page_base_address    */
575                0,                   /* avl                  */
576                0,                   /* global               */
577                0,                   /* pat                  */
578                0,                   /* dirty                */
579                0,                   /* accessed             */
580                0,                   /* cache_disabled       */
581                0,                   /* write_through        */
582                0,                   /* super_user           */
583                0,                   /* read_write           */
584                0                    /* present              */
585            );
586 }
587 
setVMRoot(tcb_t * tcb)588 void setVMRoot(tcb_t *tcb)
589 {
590     cap_t               threadRoot;
591     vspace_root_t *vspace_root;
592     asid_t              asid;
593     findVSpaceForASID_ret_t find_ret;
594 
595     threadRoot = TCB_PTR_CTE_PTR(tcb, tcbVTable)->cap;
596 
597     vspace_root = getValidNativeRoot(threadRoot);
598     if (!vspace_root) {
599         SMP_COND_STATEMENT(tlb_bitmap_unset(paddr_to_pptr(getCurrentPD()), getCurrentCPUIndex());)
600         setCurrentPD(kpptr_to_paddr(ia32KSGlobalPD));
601         return;
602     }
603 
604     asid = cap_get_capMappedASID(threadRoot);
605     find_ret = findVSpaceForASID(asid);
606     if (find_ret.status != EXCEPTION_NONE || find_ret.vspace_root != vspace_root) {
607         SMP_COND_STATEMENT(tlb_bitmap_unset(paddr_to_pptr(getCurrentPD()), getCurrentCPUIndex());)
608         setCurrentPD(kpptr_to_paddr(ia32KSGlobalPD));
609         return;
610     }
611 
612     /* only set PD if we change it, otherwise we flush the TLB needlessly */
613     if (getCurrentPD() != pptr_to_paddr(vspace_root)) {
614         SMP_COND_STATEMENT(tlb_bitmap_unset(paddr_to_pptr(getCurrentPD()), getCurrentCPUIndex());)
615         SMP_COND_STATEMENT(tlb_bitmap_set(vspace_root, getCurrentCPUIndex());)
616 
617         setCurrentPD(pptr_to_paddr(vspace_root));
618     }
619 }
620 
hwASIDInvalidate(asid_t asid,vspace_root_t * vspace)621 void hwASIDInvalidate(asid_t asid, vspace_root_t *vspace)
622 {
623     /* 32-bit does not have PCID */
624     return;
625 }
626 
decodeX86ModeMMUInvocation(word_t invLabel,word_t length,cptr_t cptr,cte_t * cte,cap_t cap,word_t * buffer)627 exception_t decodeX86ModeMMUInvocation(
628     word_t invLabel,
629     word_t length,
630     cptr_t cptr,
631     cte_t *cte,
632     cap_t cap,
633     word_t *buffer
634 )
635 {
636     switch (cap_get_capType(cap)) {
637     case cap_page_directory_cap:
638         return decodeIA32PageDirectoryInvocation(invLabel, length, cte, cap, buffer);
639 
640     default:
641         fail("Invalid arch cap type");
642     }
643 }
644 
645 
modeUnmapPage(vm_page_size_t page_size,vspace_root_t * vroot,vptr_t vaddr,void * pptr)646 bool_t modeUnmapPage(vm_page_size_t page_size, vspace_root_t *vroot, vptr_t vaddr, void *pptr)
647 {
648     fail("Invalid page type");
649     return false;
650 }
651 
decodeX86ModeMapPage(word_t invLabel,vm_page_size_t page_size,cte_t * cte,cap_t cap,vspace_root_t * vroot,vptr_t vaddr,paddr_t paddr,vm_rights_t vm_rights,vm_attributes_t vm_attr)652 exception_t decodeX86ModeMapPage(word_t invLabel, vm_page_size_t page_size, cte_t *cte, cap_t cap,
653                                  vspace_root_t *vroot, vptr_t vaddr, paddr_t paddr, vm_rights_t vm_rights, vm_attributes_t vm_attr)
654 {
655     fail("Invalid Page type");
656 }
657 
658 #ifdef CONFIG_KERNEL_LOG_BUFFER
benchmark_arch_map_logBuffer(word_t frame_cptr)659 exception_t benchmark_arch_map_logBuffer(word_t frame_cptr)
660 {
661     lookupCapAndSlot_ret_t lu_ret;
662     vm_page_size_t frameSize;
663     pptr_t frame_pptr;
664 
665     /* faulting section */
666     lu_ret = lookupCapAndSlot(NODE_STATE(ksCurThread), frame_cptr);
667 
668     if (unlikely(lu_ret.status != EXCEPTION_NONE)) {
669         userError("Invalid cap #%lu.", frame_cptr);
670         current_fault = seL4_Fault_CapFault_new(frame_cptr, false);
671 
672         return EXCEPTION_SYSCALL_ERROR;
673     }
674 
675     if (cap_get_capType(lu_ret.cap) != cap_frame_cap) {
676         userError("Invalid cap. Log buffer should be of a frame cap");
677         current_fault = seL4_Fault_CapFault_new(frame_cptr, false);
678 
679         return EXCEPTION_SYSCALL_ERROR;
680     }
681 
682     frameSize = cap_frame_cap_get_capFSize(lu_ret.cap);
683 
684     if (frameSize != X86_LargePage) {
685         userError("Invalid size for log Buffer. The kernel expects at least 1M log buffer");
686         current_fault = seL4_Fault_CapFault_new(frame_cptr, false);
687 
688         return EXCEPTION_SYSCALL_ERROR;
689     }
690 
691     frame_pptr = cap_frame_cap_get_capFBasePtr(lu_ret.cap);
692 
693     ksUserLogBuffer = pptr_to_paddr((void *) frame_pptr);
694 
695     /* fill global log page table with mappings */
696     for (int idx = 0; idx < BIT(PT_INDEX_BITS); idx++) {
697         paddr_t physical_address = ksUserLogBuffer + (idx << seL4_PageBits);
698 
699         pte_t pte = pte_new(
700                         physical_address,   /* page_base_address    */
701                         0,                  /* avl                  */
702                         1,                  /* global               */
703                         VMKernelOnly,       /* pat                  */
704                         0,                  /* dirty                */
705                         0,                  /* accessed             */
706                         0,                  /* cache_disabled       */
707                         1,                  /* write_through        */
708                         1,                  /* super_user           */
709                         1,                  /* read_write           */
710                         1                   /* present              */
711                     );
712 
713         ia32KSGlobalLogPT[idx] = pte;
714         invalidateTLBEntry(KS_LOG_PPTR + (idx << seL4_PageBits), MASK(ksNumCPUs));
715     }
716 
717     return EXCEPTION_NONE;
718 }
719 #endif /* CONFIG_KERNEL_LOG_BUFFER */
720