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 = pre_boot_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 = pre_boot_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 CONFIG_EFI 171 172 /* From x86/efi/efistart64.S */ 173 extern void load_gdt_tss(size_t tss_offset); 174 175 static efi_status_t setup_memory_allocator(efi_bootinfo_t *efi_bootinfo) 176 { 177 int i; 178 unsigned long free_mem_pages = 0; 179 unsigned long free_mem_start = 0; 180 struct efi_boot_memmap *map = &(efi_bootinfo->mem_map); 181 efi_memory_desc_t *buffer = *map->map; 182 efi_memory_desc_t *d = NULL; 183 184 /* 185 * The 'buffer' contains multiple descriptors that describe memory 186 * regions maintained by UEFI. This code records the largest free 187 * EFI_CONVENTIONAL_MEMORY region which will be used to set up the 188 * memory allocator, so that the memory allocator can work in the 189 * largest free continuous memory region. 190 */ 191 for (i = 0; i < *(map->map_size); i += *(map->desc_size)) { 192 d = (efi_memory_desc_t *)(&((u8 *)buffer)[i]); 193 if (d->type == EFI_CONVENTIONAL_MEMORY) { 194 if (free_mem_pages < d->num_pages) { 195 free_mem_pages = d->num_pages; 196 free_mem_start = d->phys_addr; 197 } 198 } 199 } 200 201 if (free_mem_pages == 0) { 202 return EFI_OUT_OF_RESOURCES; 203 } 204 205 phys_alloc_init(free_mem_start, free_mem_pages << EFI_PAGE_SHIFT); 206 207 return EFI_SUCCESS; 208 } 209 210 static efi_status_t setup_rsdp(efi_bootinfo_t *efi_bootinfo) 211 { 212 efi_status_t status; 213 struct rsdp_descriptor *rsdp; 214 215 /* 216 * RSDP resides in an EFI_ACPI_RECLAIM_MEMORY region, which is not used 217 * by kvm-unit-tests x86's memory allocator. So it is not necessary to 218 * copy the data structure to another memory region to prevent 219 * unintentional overwrite. 220 */ 221 status = efi_get_system_config_table(ACPI_TABLE_GUID, (void **)&rsdp); 222 if (status != EFI_SUCCESS) { 223 return status; 224 } 225 226 set_efi_rsdp(rsdp); 227 228 return EFI_SUCCESS; 229 } 230 231 /* Defined in cstart64.S or efistart64.S */ 232 extern u8 ptl4; 233 extern u8 ptl3; 234 extern u8 ptl2; 235 236 static void setup_page_table(void) 237 { 238 pgd_t *curr_pt; 239 phys_addr_t flags; 240 int i; 241 242 /* Set default flags */ 243 flags = PT_PRESENT_MASK | PT_WRITABLE_MASK | PT_USER_MASK; 244 245 /* Set AMD SEV C-Bit for page table entries */ 246 flags |= get_amd_sev_c_bit_mask(); 247 248 /* Level 4 */ 249 curr_pt = (pgd_t *)&ptl4; 250 curr_pt[0] = ((phys_addr_t)&ptl3) | flags; 251 /* Level 3 */ 252 curr_pt = (pgd_t *)&ptl3; 253 for (i = 0; i < 4; i++) { 254 curr_pt[i] = (((phys_addr_t)&ptl2) + i * PAGE_SIZE) | flags; 255 } 256 /* Level 2 */ 257 curr_pt = (pgd_t *)&ptl2; 258 flags |= PT_ACCESSED_MASK | PT_DIRTY_MASK | PT_PAGE_SIZE_MASK | PT_GLOBAL_MASK; 259 for (i = 0; i < 4 * 512; i++) { 260 curr_pt[i] = ((phys_addr_t) i << 21) | flags; 261 } 262 263 if (amd_sev_es_enabled()) { 264 setup_ghcb_pte((pgd_t *)&ptl4); 265 } 266 267 /* Load 4-level page table */ 268 write_cr3((ulong)&ptl4); 269 } 270 271 static void setup_gdt_tss(void) 272 { 273 size_t tss_offset; 274 275 /* 64-bit setup_tss does not use the stacktop argument. */ 276 tss_offset = setup_tss(NULL); 277 load_gdt_tss(tss_offset); 278 } 279 280 efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo) 281 { 282 efi_status_t status; 283 const char *phase; 284 285 status = setup_memory_allocator(efi_bootinfo); 286 if (status != EFI_SUCCESS) { 287 printf("Failed to set up memory allocator: "); 288 switch (status) { 289 case EFI_OUT_OF_RESOURCES: 290 printf("No free memory region\n"); 291 break; 292 default: 293 printf("Unknown error\n"); 294 break; 295 } 296 return status; 297 } 298 299 status = setup_rsdp(efi_bootinfo); 300 if (status != EFI_SUCCESS) { 301 printf("Cannot find RSDP in EFI system table\n"); 302 return status; 303 } 304 305 phase = "AMD SEV"; 306 status = setup_amd_sev(); 307 308 /* Continue if AMD SEV is not supported, but skip SEV-ES setup */ 309 if (status == EFI_SUCCESS) { 310 phase = "AMD SEV-ES"; 311 status = setup_amd_sev_es(); 312 } 313 314 if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) { 315 printf("%s setup failed, error = 0x%lx\n", phase, status); 316 return status; 317 } 318 319 reset_apic(); 320 setup_gdt_tss(); 321 setup_idt(); 322 load_idt(); 323 mask_pic_interrupts(); 324 enable_apic(); 325 ap_init(); 326 enable_x2apic(); 327 smp_init(); 328 setup_page_table(); 329 330 return EFI_SUCCESS; 331 } 332 333 #endif /* CONFIG_EFI */ 334 335 void setup_libcflat(void) 336 { 337 if (initrd) { 338 /* environ is currently the only file in the initrd */ 339 u32 size = MIN(initrd_size, ENV_SIZE); 340 const char *str; 341 342 memcpy(env, initrd, size); 343 setup_env(env, size); 344 if ((str = getenv("BOOTLOADER")) && atol(str) != 0) 345 add_setup_arg("bootloader"); 346 } 347 } 348