2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2015, The V3VEE Project <http://www.v3vee.org>
11 * All rights reserved.
13 * Author: Peter Dinda <pdinda@northwestern.edu>
15 * This is free software. You are permitted to use,
16 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
19 #include <palacios/vmm_mem.h>
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_util.h>
22 #include <palacios/vmm_emulator.h>
23 #include <palacios/vm_guest.h>
24 #include <palacios/vmm_debug.h>
25 #include <palacios/vmm_hypercall.h>
27 #include <palacios/vmm_xml.h>
29 #include <palacios/vm_guest_mem.h>
31 #include <palacios/vmm_debug.h>
39 <file id="multibootelf" filename="multibootelf.o" />
42 <multiboot enable="y" file_id="multibootelf" />
47 #ifndef V3_CONFIG_DEBUG_MULTIBOOT
49 #define PrintDebug(fmt, args...)
53 int v3_init_multiboot()
55 PrintDebug(VM_NONE,VCORE_NONE, "multiboot: init\n");
59 int v3_deinit_multiboot()
61 PrintDebug(VM_NONE,VCORE_NONE, "multiboot: deinit\n");
67 #define CEIL_DIV(x,y) (((x)/(y)) + !!((x)%(y)))
69 int v3_init_multiboot_vm(struct v3_vm_info *vm, struct v3_xml *config)
71 v3_cfg_tree_t *mb_config;
75 PrintDebug(vm, VCORE_NONE, "multiboot: vm init\n");
77 memset(&vm->mb_state,0,sizeof(struct v3_vm_multiboot));
78 vm->mb_state.is_multiboot=0;
80 if (!config || !(mb_config=v3_cfg_subtree(config,"multiboot"))) {
81 PrintDebug(vm,VCORE_NONE,"multiboot: no multiboot configuration found - normal boot will occur\n");
85 if (!(enable=v3_cfg_val(mb_config,"enable")) || strcasecmp(enable,"y")) {
86 PrintDebug(vm,VCORE_NONE,"multiboot: multiboot configuration disabled\n");
90 if (!(mb_file_id=v3_cfg_val(mb_config,"file_id"))) {
91 PrintError(vm,VCORE_NONE,"multiboot: multiboot block without file_id...\n");
95 vm->mb_state.mb_file = v3_cfg_get_file(vm,mb_file_id);
97 if (!vm->mb_state.mb_file) {
98 PrintError(vm,VCORE_NONE,"multiboot: multiboot block contains bad file_id (%s)\n",mb_file_id);
102 vm->mb_state.is_multiboot=1;
105 if (vm->mb_state.is_multiboot) {
106 V3_Print(vm,VCORE_NONE,"multiboot: file_id=%s (tag %s)]\n",
108 vm->mb_state.mb_file->tag);
110 V3_Print(vm,VCORE_NONE,"multiboot: This is not a multiboot VM\n");
117 int v3_deinit_multiboot_vm(struct v3_vm_info *vm)
119 PrintDebug(vm, VCORE_NONE, "multiboot: multiboot VM deinit\n");
124 int v3_init_multiboot_core(struct guest_info *core)
126 PrintDebug(core->vm_info, VCORE_NONE, "multiboot: multiboot core init\n");
128 // Nothing to do at this point
133 int v3_deinit_multiboot_core(struct guest_info *core)
135 PrintDebug(core->vm_info, VCORE_NONE, "multiboot: multiboot core deinit\n");
143 #define ERROR(fmt, args...) PrintError(VM_NONE,VCORE_NONE,"multiboot: " fmt,##args)
144 #define INFO(fmt, args...) PrintDebug(VM_NONE,VCORE_NONE,"multiboot: " fmt,##args)
147 static int is_elf(uint8_t *data, uint64_t size)
149 if (*((uint32_t*)data)==ELF_MAGIC) {
156 static mb_header_t *find_mb_header(uint8_t *data, uint64_t size)
158 uint64_t limit = size > 32768 ? 32768 : size;
161 // Scan for the .boot magic cookie
162 // must be in first 32K, assume 4 byte aligned
163 for (i=0;i<limit;i+=4) {
164 if (*((uint32_t*)&data[i])==MB2_MAGIC) {
165 INFO("Found multiboot header at offset 0x%llx\n",i);
166 return (mb_header_t *) &data[i];
172 static int checksum4_ok(uint32_t *data, uint64_t size)
177 for (i=0;i<size;i++) {
184 static int parse_multiboot_kernel(uint8_t *data, uint64_t size, mb_data_t *mb)
188 mb_header_t *mb_header=0;
191 mb_addr_t *mb_addr=0;
192 mb_entry_t *mb_entry=0;
193 mb_flags_t *mb_flags=0;
194 mb_framebuf_t *mb_framebuf=0;
195 mb_modalign_t *mb_modalign=0;
196 mb_mb64_hrt_t *mb_mb64_hrt=0;
199 if (!is_elf(data,size)) {
200 ERROR("HRT is not an ELF\n");
204 mb_header = find_mb_header(data,size);
207 ERROR("No multiboot header found\n");
211 // Checksum applies only to the header itself, not to
212 // the subsequent tags...
213 if (!checksum4_ok((uint32_t*)mb_header,4)) {
214 ERROR("Multiboot header has bad checksum\n");
218 INFO("Multiboot header: arch=0x%x, headerlen=0x%x\n", mb_header->arch, mb_header->headerlen);
220 mb_tag = (mb_tag_t*)((void*)mb_header+16);
222 while (!(mb_tag->type==0 && mb_tag->size==8)) {
223 INFO("tag: type 0x%x flags=0x%x size=0x%x\n",mb_tag->type, mb_tag->flags,mb_tag->size);
224 switch (mb_tag->type) {
227 ERROR("Multiple info tags found!\n");
230 mb_inf = (mb_info_t*)mb_tag;
231 INFO(" info request - types follow\n");
232 for (i=0;(mb_tag->size-8)/4;i++) {
233 INFO(" %llu: type 0x%x\n", i, mb_inf->types[i]);
238 case MB_TAG_ADDRESS: {
240 ERROR("Multiple address tags found!\n");
243 mb_addr = (mb_addr_t*)mb_tag;
245 INFO(" header_addr = 0x%x\n", mb_addr->header_addr);
246 INFO(" load_addr = 0x%x\n", mb_addr->load_addr);
247 INFO(" load_end_addr = 0x%x\n", mb_addr->load_end_addr);
248 INFO(" bss_end_addr = 0x%x\n", mb_addr->bss_end_addr);
254 ERROR("Multiple entry tags found!\n");
257 mb_entry=(mb_entry_t*)mb_tag;
259 INFO(" entry_addr = 0x%x\n", mb_entry->entry_addr);
265 ERROR("Multiple flags tags found!\n");
268 mb_flags = (mb_flags_t*)mb_tag;
270 INFO(" console_flags = 0x%x\n", mb_flags->console_flags);
274 case MB_TAG_FRAMEBUF: {
276 ERROR("Multiple framebuf tags found!\n");
279 mb_framebuf = (mb_framebuf_t*)mb_tag;
281 INFO(" width = 0x%x\n", mb_framebuf->width);
282 INFO(" height = 0x%x\n", mb_framebuf->height);
283 INFO(" depth = 0x%x\n", mb_framebuf->depth);
287 case MB_TAG_MODALIGN: {
289 ERROR("Multiple modalign tags found!\n");
292 mb_modalign = (mb_modalign_t*)mb_tag;
294 INFO(" size = 0x%x\n", mb_modalign->size);
299 case MB_TAG_MB64_HRT: {
301 ERROR("Multiple mb64_hrt tags found!\n");
304 mb_mb64_hrt = (mb_mb64_hrt_t*)mb_tag;
310 INFO("Unknown tag... Skipping...\n");
313 mb_tag = (mb_tag_t *)(((void*)mb_tag) + mb_tag->size);
316 // copy out to caller
317 mb->header=mb_header;
322 mb->framebuf=mb_framebuf;
323 mb->modalign=mb_modalign;
324 mb->mb64_hrt=mb_mb64_hrt;
330 int v3_parse_multiboot_header(struct v3_cfg_file *file, mb_data_t *result)
332 return parse_multiboot_kernel(file->data,file->size,result);
336 #define APIC_BASE 0xfee00000
337 #define IOAPIC_BASE 0xfec00000
341 MB_HRT (if this is an HVM
346 1024..ioapic_base RAM
347 ioapic_base to ioapic_base+page reserved
348 ioapic_base+page to apic_base ram
349 apic_base oto apic_base+page reserved
350 apic_base+page to total RAM
353 The multiboot structure that is written reflects the
354 perspective of the core given the kind of VM it is part of.
357 - core does not matter
362 - only ROS memory visible
363 - regular multiboot or bios boot assumed
366 - HRT64 multiboot assumed
370 uint64_t v3_build_multiboot_table(struct guest_info *core, uint8_t *dest, uint64_t size)
372 struct v3_vm_info *vm = core->vm_info;
373 mb_info_header_t *header=0;
375 mb_info_hrt_t *hrt=0;
377 mb_info_mem_t *mem=0;
378 mb_info_memmap_t *memmap=0;
379 mb_info_tag_t *tag=0;
380 uint64_t num_mem=0, cur_mem=0;
382 uint64_t total_mem = vm->mem_size;
385 if (vm->hvm_state.is_hvm) {
386 if (v3_is_hvm_ros_core(core)) {
387 PrintDebug(core->vm_info,core,"multiboot: hvm: building mb table from ROS core perspective\n");
388 total_mem = v3_get_hvm_ros_memsize(vm);
390 PrintDebug(core->vm_info,core,"multiboot: hvm: building mb table from HRT core perspective\n");
391 total_mem = v3_get_hvm_hrt_memsize(vm);
396 // assume we have > 1 MB + apic+ioapic
398 if (total_mem>IOAPIC_BASE+PAGE_SIZE) {
401 if (total_mem>APIC_BASE+PAGE_SIZE) {
407 sizeof(mb_info_header_t) +
409 core->vm_info->hvm_state.is_hvm && core->hvm_state.is_hrt ? sizeof(mb_info_hrt_t) : 0
412 sizeof(mb_info_mem_t) +
413 sizeof(mb_info_memmap_t) +
414 sizeof(mb_info_memmap_entry_t) * num_mem +
415 sizeof(mb_info_tag_t);
424 ERROR("Cannot fit MB info in needed space\n");
430 header = (mb_info_header_t*)next;
431 next += sizeof(mb_info_header_t);
434 if (core->vm_info->hvm_state.is_hvm && v3_is_hvm_hrt_core(core)) {
435 hrt = (mb_info_hrt_t*)next;
436 next += sizeof(mb_info_hrt_t);
440 mem = (mb_info_mem_t*)next;
441 next += sizeof(mb_info_mem_t);
443 memmap = (mb_info_memmap_t*)next;
444 next += sizeof(mb_info_memmap_t) + num_mem * sizeof(mb_info_memmap_entry_t);
446 tag = (mb_info_tag_t*)next;
447 next += sizeof(mb_info_tag_t);
449 header->totalsize = (uint32_t)(next - dest);
450 header->reserved = 0;
453 if (core->vm_info->hvm_state.is_hvm && v3_is_hvm_hrt_core(core)) {
454 v3_build_hrt_multiboot_tag(core,hrt);
458 mem->tag.type = MB_INFO_MEM_TAG;
459 mem->tag.size = sizeof(mb_info_mem_t);
460 mem->mem_lower = 640; // thank you, bill gates
461 mem->mem_upper = (total_mem - 1024 * 1024) / 1024;
463 memmap->tag.type = MB_INFO_MEMMAP_TAG;
464 memmap->tag.size = sizeof(mb_info_memmap_t) + num_mem * sizeof(mb_info_memmap_entry_t);
465 memmap->entry_size = 24;
466 memmap->entry_version = 0;
471 memmap->entries[cur_mem].base_addr = 0;
472 memmap->entries[cur_mem].length = 640*1024;
473 memmap->entries[cur_mem].type = MEM_RAM;
474 memmap->entries[cur_mem].reserved = 0;
477 // legacy io (640K->1 MB)
478 memmap->entries[cur_mem].base_addr = 640*1024;
479 memmap->entries[cur_mem].length = 384*1024;
480 memmap->entries[cur_mem].type = MEM_RESV;
481 memmap->entries[cur_mem].reserved = 1;
484 // first meg to ioapic
485 memmap->entries[cur_mem].base_addr = 1024*1024;
486 memmap->entries[cur_mem].length = (total_mem < IOAPIC_BASE ? total_mem : IOAPIC_BASE) - 1024*1024;
487 memmap->entries[cur_mem].type = MEM_RAM;
488 memmap->entries[cur_mem].reserved = 0;
491 // ioapic reservation
492 memmap->entries[cur_mem].base_addr = IOAPIC_BASE;
493 memmap->entries[cur_mem].length = PAGE_SIZE;
494 memmap->entries[cur_mem].type = MEM_RESV;
495 memmap->entries[cur_mem].reserved = 1;
498 if (total_mem > (IOAPIC_BASE + PAGE_SIZE)) {
499 // memory between ioapic and apic
500 memmap->entries[cur_mem].base_addr = IOAPIC_BASE+PAGE_SIZE;
501 memmap->entries[cur_mem].length = (total_mem < APIC_BASE ? total_mem : APIC_BASE) - (IOAPIC_BASE+PAGE_SIZE);;
502 memmap->entries[cur_mem].type = MEM_RAM;
503 memmap->entries[cur_mem].reserved = 0;
508 memmap->entries[cur_mem].base_addr = APIC_BASE;
509 memmap->entries[cur_mem].length = PAGE_SIZE;
510 memmap->entries[cur_mem].type = MEM_RESV;
511 memmap->entries[cur_mem].reserved = 1;
514 if (total_mem > (APIC_BASE + PAGE_SIZE)) {
516 memmap->entries[cur_mem].base_addr = APIC_BASE+PAGE_SIZE;
517 memmap->entries[cur_mem].length = total_mem - (APIC_BASE+PAGE_SIZE);
518 memmap->entries[cur_mem].type = MEM_RAM;
519 memmap->entries[cur_mem].reserved = 0;
523 for (cur_mem=0;cur_mem<num_mem;cur_mem++) {
524 PrintDebug(vm, VCORE_NONE,
525 "multiboot: entry %llu: %p (%llx bytes) - type %x %s\n",
527 (void*) memmap->entries[cur_mem].base_addr,
528 memmap->entries[cur_mem].length,
529 memmap->entries[cur_mem].type,
530 memmap->entries[cur_mem].reserved ? "reserved" : "");
535 // This demarcates end of list
539 return header->totalsize;
544 int v3_write_multiboot_kernel(struct v3_vm_info *vm, mb_data_t *mb, struct v3_cfg_file *file,
545 void *base, uint64_t limit)
548 uint32_t header_offset = (uint32_t) ((uint64_t)(mb->header) - (uint64_t)(file->data));
551 if (!mb->addr || !mb->entry) {
552 PrintError(vm,VCORE_NONE, "multiboot: kernel is missing address or entry point\n");
556 if (((void*)(uint64_t)(mb->addr->header_addr) < base ) ||
557 ((void*)(uint64_t)(mb->addr->load_end_addr) > base+limit) ||
558 ((void*)(uint64_t)(mb->addr->bss_end_addr) > base+limit)) {
559 PrintError(vm,VCORE_NONE, "multiboot: kernel is not within the allowed portion of VM\n");
563 offset = header_offset - (mb->addr->header_addr - mb->addr->load_addr);
564 size = mb->addr->load_end_addr - mb->addr->load_addr;
566 if (size != file->size-offset) {
567 V3_Print(vm,VCORE_NONE,"multiboot: strange: size computed as %u, but file->size-offset = %llu\n",size,file->size-offset);
570 // We are trying to do as little ELF loading here as humanly possible
571 v3_write_gpa_memory(&vm->cores[0],
572 (addr_t)(mb->addr->load_addr),
576 PrintDebug(vm,VCORE_NONE,
577 "multiboot: wrote 0x%llx bytes starting at offset 0x%llx to %p\n",
580 (void*)(addr_t)(mb->addr->load_addr));
582 size = mb->addr->bss_end_addr - mb->addr->load_end_addr + 1;
584 // Now we need to zero the BSS
585 v3_set_gpa_memory(&vm->cores[0],
586 (addr_t)(mb->addr->load_end_addr),
590 PrintDebug(vm,VCORE_NONE,
591 "multiboot: zeroed 0x%llx bytes starting at %p\n",
593 (void*)(addr_t)(mb->addr->load_end_addr));
601 static int setup_multiboot_kernel(struct v3_vm_info *vm)
604 uint64_t limit = vm->mem_size;
607 if (vm->mb_state.mb_file->size > limit) {
608 PrintError(vm,VCORE_NONE,"multiboot: Cannot map kernel because it is too big (%llu bytes, but only have %llu space\n", vm->mb_state.mb_file->size, (uint64_t)limit);
612 if (!is_elf(vm->mb_state.mb_file->data,vm->mb_state.mb_file->size)) {
613 PrintError(vm,VCORE_NONE,"multiboot: supplied kernel is not an ELF\n");
616 if (find_mb_header(vm->mb_state.mb_file->data,vm->mb_state.mb_file->size)) {
617 PrintDebug(vm,VCORE_NONE,"multiboot: appears to be a multiboot kernel\n");
618 if (v3_parse_multiboot_header(vm->mb_state.mb_file,&vm->mb_state.mb_data)) {
619 PrintError(vm,VCORE_NONE,"multiboot: cannot parse multiboot kernel header\n");
622 if (v3_write_multiboot_kernel(vm, &(vm->mb_state.mb_data),vm->mb_state.mb_file,base,limit)) {
623 PrintError(vm,VCORE_NONE,"multiboot: multiboot kernel setup failed\n");
627 PrintError(vm,VCORE_NONE,"multiboot: multiboot kernel has no header\n");
636 // 32 bit GDT entries
638 // base24-31 flags2 limit16-19 access8 base16-23 base0-15 limit0-15
639 // null 0 0 0 0 0 0 0
640 // code 0 1100 f 10011010 0 0 ffff
641 // data 0 1100 f 10010010 0 0 ffff
643 // null = 00 00 00 00 00 00 00 00
644 // code = 00 cf 9a 00 00 00 ff ff
645 // data = 00 cf 92 00 00 00 ff ff
647 static uint64_t gdt32[3] = {
648 0x0000000000000000, /* null */
649 0x00cf9a000000ffff, /* code (note lme=0) */
650 0x00cf92000000ffff, /* data */
653 static void write_gdt(struct v3_vm_info *vm, void *base, uint64_t limit)
655 v3_write_gpa_memory(&vm->cores[0],(addr_t)base,limit,(uint8_t*) gdt32);
657 PrintDebug(vm,VCORE_NONE,"multiboot: wrote GDT at %p\n",base);
661 static void write_tss(struct v3_vm_info *vm, void *base, uint64_t limit)
663 v3_set_gpa_memory(&vm->cores[0],(addr_t)base,limit,0);
665 PrintDebug(vm,VCORE_NONE,"multiboot: wrote TSS at %p\n",base);
668 static void write_table(struct v3_vm_info *vm, void *base, uint64_t limit)
673 limit = limit < 256 ? limit : 256;
675 size = v3_build_multiboot_table(&vm->cores[0], buf, limit);
677 if (size>256 || size==0) {
678 PrintError(vm,VCORE_NONE,"multiboot: cannot build multiboot table\n");
682 v3_write_gpa_memory(&vm->cores[0],(addr_t)base,size,buf);
694 Kernel at its desired load address (or error)
699 int v3_setup_multiboot_vm_for_boot(struct v3_vm_info *vm)
701 void *kernel_start_gpa;
702 void *kernel_end_gpa;
707 if (!vm->mb_state.is_multiboot) {
708 PrintDebug(vm,VCORE_NONE,"multiboot: skipping multiboot setup for boot as this is not a multiboot VM\n");
713 if (setup_multiboot_kernel(vm)) {
714 PrintError(vm,VCORE_NONE,"multiboot: failed to setup kernel\n");
718 kernel_start_gpa = (void*) (uint64_t) (vm->mb_state.mb_data.addr->load_addr);
719 kernel_end_gpa = (void*) (uint64_t) (vm->mb_state.mb_data.addr->bss_end_addr);
721 // Is there room below the kernel?
722 if ((uint64_t)kernel_start_gpa > 19*4096 ) {
723 // at least 3 pages between 64K and start of kernel
725 mb_gpa=(void*)(16*4096);
727 // is there room above the kernel?
728 if ((uint64_t)kernel_end_gpa < vm->mem_size-4*4096) {
729 if (((uint64_t)kernel_end_gpa + 4 * 4096) <= 0xffffffff) {
730 mb_gpa=(void*) (4096*((uint64_t)kernel_end_gpa/4096 + 1));
732 PrintError(vm,VCORE_NONE,"multiboot: no room for mb data below 4 GB\n");
736 PrintError(vm,VCORE_NONE,"multiboot: no room for mb data above kernel\n");
741 PrintDebug(vm,VCORE_NONE,"multiboot: mb data will start at %p\n",mb_gpa);
743 vm->mb_state.mb_data_gpa=mb_gpa;
745 tss_gpa = mb_gpa + 1 * 4096;
746 gdt_gpa = mb_gpa + 2 * 4096;
748 write_table(vm,mb_gpa,4096);
750 write_tss(vm,tss_gpa,4096);
752 write_gdt(vm,gdt_gpa,4096);
754 PrintDebug(vm,VCORE_NONE,"multiboot: setup of memory done\n");
763 GDTR points to stub GDT
764 TR points to stub TSS
765 CR0 has PE and not PG
766 EIP is entry point to kernel
767 EBX points to multiboot info
768 EAX multiboot magic cookie
771 int v3_setup_multiboot_core_for_boot(struct guest_info *core)
776 if (!core->vm_info->mb_state.is_multiboot) {
777 PrintDebug(core->vm_info,core,"multiboot: skipping mb core setup as this is not an mb VM\n");
781 if (core->vcpu_id != 0) {
782 PrintDebug(core->vm_info,core,"multiboot: skipping mb core setup as this is not the BSP core\n");
787 PrintDebug(core->vm_info, core, "multiboot: setting up MB BSP core for boot\n");
790 memset(&core->vm_regs,0,sizeof(core->vm_regs));
791 memset(&core->ctrl_regs,0,sizeof(core->ctrl_regs));
792 memset(&core->dbg_regs,0,sizeof(core->dbg_regs));
793 memset(&core->segments,0,sizeof(core->segments));
794 memset(&core->msrs,0,sizeof(core->msrs));
795 memset(&core->fp_state,0,sizeof(core->fp_state));
797 // We need to be in protected mode at ring zero
798 core->cpl = 0; // we are going right into the kernel
799 core->cpu_mode = PROTECTED;
800 core->mem_mode = PHYSICAL_MEM;
801 // default run-state is fine, we are core zero
802 // core->core_run_state = CORE_RUNNING ;
804 // right into the kernel
805 core->rip = (uint64_t) core->vm_info->mb_state.mb_data.entry->entry_addr;
807 // Setup CRs for protected mode
808 // CR0: PE (but no PG)
809 core->ctrl_regs.cr0 = 0x1;
810 core->shdw_pg_state.guest_cr0 = core->ctrl_regs.cr0;
812 // CR2: don't care (output from #PF)
813 // CR3: don't care (no paging)
814 core->ctrl_regs.cr3 = 0;
815 core->shdw_pg_state.guest_cr3 = core->ctrl_regs.cr3;
818 core->ctrl_regs.cr4 = 0x0;
819 core->shdw_pg_state.guest_cr4 = core->ctrl_regs.cr4;
821 // RFLAGS zeroed is fine: come in with interrupts off
822 // EFER needs SVME and LME but not LMA (last 16 bits: 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0
823 core->ctrl_regs.efer = 0x1400;
824 core->shdw_pg_state.guest_efer.value = core->ctrl_regs.efer;
830 selector is 13 bits of index, 1 bit table indicator
833 index is scaled by 8, even in long mode, where some entries
834 are 16 bytes long....
835 -> code, data descriptors have 8 byte format
836 because base, limit, etc, are ignored (no segmentation)
837 -> interrupt/trap gates have 16 byte format
838 because offset needs to be 64 bits
841 // There is no IDTR set and interrupts are disabled
843 // Install our stub GDT
844 core->segments.gdtr.selector = 0;
845 core->segments.gdtr.base = (addr_t) core->vm_info->mb_state.mb_data_gpa+2*4096;
846 core->segments.gdtr.limit = 4096-1;
847 core->segments.gdtr.type = 0x6;
848 core->segments.gdtr.system = 1;
849 core->segments.gdtr.dpl = 0;
850 core->segments.gdtr.present = 1;
851 core->segments.gdtr.long_mode = 0;
854 core->segments.tr.selector = 0;
855 core->segments.tr.base = (addr_t) core->vm_info->mb_state.mb_data_gpa+1*4096;
856 core->segments.tr.limit = 4096-1;
857 core->segments.tr.type = 0x6;
858 core->segments.tr.system = 1;
859 core->segments.tr.dpl = 0;
860 core->segments.tr.present = 1;
861 core->segments.tr.long_mode = 0;
867 core->segments.cs.selector = 0x8 ; // entry 1 of GDT (RPL=0)
868 core->segments.cs.base = (addr_t) base;
869 core->segments.cs.limit = limit;
870 core->segments.cs.type = 0xa;
871 core->segments.cs.system = 1;
872 core->segments.cs.dpl = 0;
873 core->segments.cs.present = 1;
874 core->segments.cs.long_mode = 0;
875 core->segments.cs.db = 1; // 32 bit operand and address size
876 core->segments.cs.granularity = 1; // pages
878 // DS, SS, etc are identical
879 core->segments.ds.selector = 0x10; // entry 2 of GDT (RPL=0)
880 core->segments.ds.base = (addr_t) base;
881 core->segments.ds.limit = limit;
882 core->segments.ds.type = 0x2;
883 core->segments.ds.system = 1;
884 core->segments.ds.dpl = 0;
885 core->segments.ds.present = 1;
886 core->segments.ds.long_mode = 0;
887 core->segments.ds.db = 1; // 32 bit operand and address size
888 core->segments.ds.granularity = 1; // pages
890 memcpy(&core->segments.ss,&core->segments.ds,sizeof(core->segments.ds));
891 memcpy(&core->segments.es,&core->segments.ds,sizeof(core->segments.ds));
892 memcpy(&core->segments.fs,&core->segments.ds,sizeof(core->segments.ds));
893 memcpy(&core->segments.gs,&core->segments.ds,sizeof(core->segments.ds));
897 // Now for our magic - this signals
898 // the kernel that a multiboot loader loaded it
899 // and that rbx points to its offered data
900 core->vm_regs.rax = MB2_INFO_MAGIC;
902 core->vm_regs.rbx = (uint64_t) (core->vm_info->mb_state.mb_data_gpa);
904 // reset paging here for shadow...
906 if (core->shdw_pg_mode != NESTED_PAGING) {
907 PrintError(core->vm_info, core, "multiboot: shadow paging guest... this will end badly\n");
916 int v3_handle_multiboot_reset(struct guest_info *core)
920 if (core->core_run_state!=CORE_RESETTING) {
924 if (!core->vm_info->mb_state.is_multiboot) {
929 v3_counting_barrier(&core->vm_info->reset_barrier);
931 if (core->vcpu_id==0) {
932 // I am leader (this is true if I am a ROS core or this is a non-HVM)
933 core->vm_info->run_state = VM_RESETTING;
938 if (core->vcpu_id==0) {
939 // we will recopy the image
940 rc |= v3_setup_multiboot_vm_for_boot(core->vm_info);
943 rc |= v3_setup_multiboot_core_for_boot(core);
945 if (core->vcpu_id==0) {
946 core->core_run_state = CORE_RUNNING;
947 core->vm_info->run_state = VM_RUNNING;
949 // for APs, we need to bring them back to the init state
950 core->cpu_mode = REAL;
951 core->mem_mode = PHYSICAL_MEM;
952 core->core_run_state = CORE_STOPPED;
955 // sync on the way out
956 v3_counting_barrier(&core->vm_info->reset_barrier);