1 /* 2 * Initialize machine setup information 3 * 4 * Copyright (C) 2017, Red Hat Inc, Andrew Jones <drjones@redhat.com> 5 * Copyright (C) 2021, Google Inc, Zixuan Wang <zixuanwang@google.com> 6 * 7 * This work is licensed under the terms of the GNU LGPL, version 2. 8 */ 9 #include "libcflat.h" 10 #include "fwcfg.h" 11 #include "alloc_phys.h" 12 #include "argv.h" 13 #include "desc.h" 14 #include "apic.h" 15 #include "apic-defs.h" 16 #include "asm/setup.h" 17 18 extern char edata; 19 20 struct mbi_bootinfo { 21 u32 flags; 22 u32 mem_lower; 23 u32 mem_upper; 24 u32 boot_device; 25 u32 cmdline; 26 u32 mods_count; 27 u32 mods_addr; 28 u32 reserved[4]; /* 28-43 */ 29 u32 mmap_length; 30 u32 mmap_addr; 31 u32 reserved0[3]; /* 52-63 */ 32 u32 bootloader; 33 u32 reserved1[5]; /* 68-87 */ 34 u32 size; 35 }; 36 37 struct mbi_module { 38 u32 start, end; 39 u32 cmdline; 40 u32 unused; 41 }; 42 43 struct mbi_mem { 44 u32 size; 45 u64 base_addr; 46 u64 length; 47 u32 type; 48 } __attribute__((packed)); 49 50 #define ENV_SIZE 16384 51 52 void setup_env(char *env, int size); 53 void setup_multiboot(struct mbi_bootinfo *bootinfo); 54 void setup_libcflat(void); 55 56 char *initrd; 57 u32 initrd_size; 58 59 static char env[ENV_SIZE]; 60 static struct mbi_bootinfo *bootinfo; 61 62 #define HUGEPAGE_SIZE (1 << 21) 63 64 #ifdef __x86_64__ 65 void find_highmem(void) 66 { 67 /* Memory above 4 GB is only supported on 64-bit systems. */ 68 if (!(bootinfo->flags & 64)) 69 return; 70 71 u64 upper_end = bootinfo->mem_upper * 1024ull; 72 u64 best_start = (uintptr_t) &edata; 73 u64 best_end = upper_end; 74 u64 max_end = fwcfg_get_u64(FW_CFG_MAX_RAM); 75 if (max_end == 0) 76 max_end = -1ull; 77 bool found = false; 78 79 uintptr_t mmap = bootinfo->mmap_addr; 80 while (mmap < bootinfo->mmap_addr + bootinfo->mmap_length) { 81 struct mbi_mem *mem = (void *)mmap; 82 mmap += mem->size + 4; 83 if (mem->type != 1) 84 continue; 85 if (mem->base_addr <= (uintptr_t) &edata || 86 (mem->base_addr <= upper_end && mem->base_addr + mem->length <= upper_end)) 87 continue; 88 if (mem->length < best_end - best_start) 89 continue; 90 if (mem->base_addr >= max_end) 91 continue; 92 best_start = mem->base_addr; 93 best_end = mem->base_addr + mem->length; 94 if (best_end > max_end) 95 best_end = max_end; 96 found = true; 97 } 98 99 if (found) { 100 best_start = (best_start + HUGEPAGE_SIZE - 1) & -HUGEPAGE_SIZE; 101 best_end = best_end & -HUGEPAGE_SIZE; 102 phys_alloc_init(best_start, best_end - best_start); 103 } 104 } 105 106 /* Setup TSS for the current processor, and return TSS offset within GDT */ 107 unsigned long setup_tss(u8 *stacktop) 108 { 109 u32 id; 110 tss64_t *tss_entry; 111 112 id = apic_id(); 113 114 /* Runtime address of current TSS */ 115 tss_entry = &tss[id]; 116 117 /* Update TSS */ 118 memset((void *)tss_entry, 0, sizeof(tss64_t)); 119 120 /* Update TSS descriptors; each descriptor takes up 2 entries */ 121 set_gdt_entry(TSS_MAIN + id * 16, (unsigned long)tss_entry, 0xffff, 0x89, 0); 122 123 return TSS_MAIN + id * 16; 124 } 125 #else 126 /* Setup TSS for the current processor, and return TSS offset within GDT */ 127 unsigned long setup_tss(u8 *stacktop) 128 { 129 u32 id; 130 tss32_t *tss_entry; 131 132 id = apic_id(); 133 134 /* Runtime address of current TSS */ 135 tss_entry = &tss[id]; 136 137 /* Update TSS */ 138 memset((void *)tss_entry, 0, sizeof(tss32_t)); 139 tss_entry->ss0 = KERNEL_DS; 140 141 /* Update descriptors for TSS and percpu data segment. */ 142 set_gdt_entry(TSS_MAIN + id * 8, 143 (unsigned long)tss_entry, 0xffff, 0x89, 0); 144 set_gdt_entry(TSS_MAIN + MAX_TEST_CPUS * 8 + id * 8, 145 (unsigned long)stacktop - 4096, 0xfffff, 0x93, 0xc0); 146 147 return TSS_MAIN + id * 8; 148 } 149 #endif 150 151 void setup_multiboot(struct mbi_bootinfo *bi) 152 { 153 struct mbi_module *mods; 154 155 bootinfo = bi; 156 157 u64 best_start = (uintptr_t) &edata; 158 u64 best_end = bootinfo->mem_upper * 1024ull; 159 phys_alloc_init(best_start, best_end - best_start); 160 161 if (bootinfo->mods_count != 1) 162 return; 163 164 mods = (struct mbi_module *)(uintptr_t) bootinfo->mods_addr; 165 166 initrd = (char *)(uintptr_t) mods->start; 167 initrd_size = mods->end - mods->start; 168 } 169 170 #ifdef TARGET_EFI 171 172 /* From x86/efi/efistart64.S */ 173 extern void load_idt(void); 174 extern void load_gdt_tss(size_t tss_offset); 175 176 void setup_efi_bootinfo(efi_bootinfo_t *efi_bootinfo) 177 { 178 efi_bootinfo->free_mem_size = 0; 179 efi_bootinfo->free_mem_start = 0; 180 efi_bootinfo->rsdp = NULL; 181 } 182 183 static efi_status_t setup_pre_boot_memory(unsigned long *mapkey, efi_bootinfo_t *efi_bootinfo) 184 { 185 int i; 186 unsigned long free_mem_total_pages; 187 efi_status_t status; 188 struct efi_boot_memmap map; 189 efi_memory_desc_t *buffer, *d; 190 unsigned long map_size, desc_size, buff_size; 191 u32 desc_ver; 192 193 map.map = &buffer; 194 map.map_size = &map_size; 195 map.desc_size = &desc_size; 196 map.desc_ver = &desc_ver; 197 map.buff_size = &buff_size; 198 map.key_ptr = mapkey; 199 200 status = efi_get_memory_map(&map); 201 if (status != EFI_SUCCESS) { 202 return status; 203 } 204 205 /* 206 * The 'buffer' contains multiple descriptors that describe memory 207 * regions maintained by UEFI. This code records the largest free 208 * EFI_CONVENTIONAL_MEMORY region which will be used to set up the 209 * memory allocator, so that the memory allocator can work in the 210 * largest free continuous memory region. 211 */ 212 free_mem_total_pages = 0; 213 for (i = 0; i < map_size; i += desc_size) { 214 d = (efi_memory_desc_t *)(&((u8 *)buffer)[i]); 215 if (d->type == EFI_CONVENTIONAL_MEMORY) { 216 if (free_mem_total_pages < d->num_pages) { 217 free_mem_total_pages = d->num_pages; 218 efi_bootinfo->free_mem_size = free_mem_total_pages << EFI_PAGE_SHIFT; 219 efi_bootinfo->free_mem_start = d->phys_addr; 220 } 221 } 222 } 223 224 if (efi_bootinfo->free_mem_size == 0) { 225 return EFI_OUT_OF_RESOURCES; 226 } 227 228 return EFI_SUCCESS; 229 } 230 231 static efi_status_t setup_pre_boot_rsdp(efi_bootinfo_t *efi_bootinfo) 232 { 233 return efi_get_system_config_table(ACPI_TABLE_GUID, (void **)&efi_bootinfo->rsdp); 234 } 235 236 efi_status_t setup_efi_pre_boot(unsigned long *mapkey, efi_bootinfo_t *efi_bootinfo) 237 { 238 efi_status_t status; 239 240 status = setup_pre_boot_memory(mapkey, efi_bootinfo); 241 if (status != EFI_SUCCESS) { 242 printf("setup_pre_boot_memory() failed: "); 243 switch (status) { 244 case EFI_OUT_OF_RESOURCES: 245 printf("No free memory region\n"); 246 break; 247 default: 248 printf("Unknown error\n"); 249 break; 250 } 251 return status; 252 } 253 254 status = setup_pre_boot_rsdp(efi_bootinfo); 255 if (status != EFI_SUCCESS) { 256 printf("Cannot find RSDP in EFI system table\n"); 257 return status; 258 } 259 260 status = setup_amd_sev(); 261 if (status != EFI_SUCCESS) { 262 switch (status) { 263 case EFI_UNSUPPORTED: 264 /* Continue if AMD SEV is not supported */ 265 break; 266 default: 267 printf("Set up AMD SEV failed\n"); 268 return status; 269 } 270 } 271 272 status = setup_amd_sev_es(); 273 if (status != EFI_SUCCESS) { 274 switch (status) { 275 case EFI_UNSUPPORTED: 276 /* Continue if AMD SEV-ES is not supported */ 277 break; 278 default: 279 printf("Set up AMD SEV-ES failed\n"); 280 return status; 281 } 282 } 283 284 return EFI_SUCCESS; 285 } 286 287 /* Defined in cstart64.S or efistart64.S */ 288 extern u8 ptl4; 289 extern u8 ptl3; 290 extern u8 ptl2; 291 292 static void setup_page_table(void) 293 { 294 pgd_t *curr_pt; 295 phys_addr_t flags; 296 int i; 297 298 /* Set default flags */ 299 flags = PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK; 300 301 /* Set AMD SEV C-Bit for page table entries */ 302 flags |= get_amd_sev_c_bit_mask(); 303 304 /* Level 4 */ 305 curr_pt = (pgd_t *)&ptl4; 306 curr_pt[0] = ((phys_addr_t)&ptl3) | flags; 307 /* Level 3 */ 308 curr_pt = (pgd_t *)&ptl3; 309 for (i = 0; i < 4; i++) { 310 curr_pt[i] = (((phys_addr_t)&ptl2) + i * PAGE_SIZE) | flags; 311 } 312 /* Level 2 */ 313 curr_pt = (pgd_t *)&ptl2; 314 flags |= PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_PAGE_SIZE_MASK | PT_GLOBAL_MASK; 315 for (i = 0; i < 4 * 512; i++) { 316 curr_pt[i] = ((phys_addr_t)(i << 21)) | flags; 317 } 318 319 if (amd_sev_es_enabled()) { 320 setup_ghcb_pte((pgd_t *)&ptl4); 321 } 322 323 /* Load 4-level page table */ 324 write_cr3((ulong)&ptl4); 325 } 326 327 static void setup_gdt_tss(void) 328 { 329 size_t tss_offset; 330 331 /* 64-bit setup_tss does not use the stacktop argument. */ 332 tss_offset = setup_tss(NULL); 333 load_gdt_tss(tss_offset); 334 } 335 336 void setup_efi(efi_bootinfo_t *efi_bootinfo) 337 { 338 reset_apic(); 339 setup_gdt_tss(); 340 setup_idt(); 341 load_idt(); 342 mask_pic_interrupts(); 343 enable_apic(); 344 enable_x2apic(); 345 smp_init(); 346 phys_alloc_init(efi_bootinfo->free_mem_start, efi_bootinfo->free_mem_size); 347 setup_efi_rsdp(efi_bootinfo->rsdp); 348 setup_page_table(); 349 } 350 351 #endif /* TARGET_EFI */ 352 353 void setup_libcflat(void) 354 { 355 if (initrd) { 356 /* environ is currently the only file in the initrd */ 357 u32 size = MIN(initrd_size, ENV_SIZE); 358 const char *str; 359 360 memcpy(env, initrd, size); 361 setup_env(env, size); 362 if ((str = getenv("BOOTLOADER")) && atol(str) != 0) 363 add_setup_arg("bootloader"); 364 } 365 } 366