/*************************************************************************************** * Copyright (c) 2014-2022 Zihao Yu, Nanjing University * * NEMU is licensed under Mulan PSL v2. * You can use this software according to the terms and conditions of the Mulan PSL v2. * You may obtain a copy of Mulan PSL v2 at: * http://license.coscl.org.cn/MulanPSL2 * * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * * See the Mulan PSL v2 for more details. ***************************************************************************************/ #include "common.h" #if defined(CONFIG_ISA_x86) bool gdb_memcpy_to_qemu(uint32_t, void *, int); bool gdb_getregs(union isa_gdb_regs *); bool gdb_setregs(union isa_gdb_regs *); void difftest_exec(uint64_t n); static uint8_t mbr[] = { // start16: 0xfa, // cli 0x31, 0xc0, // xorw %ax,%ax 0x8e, 0xd8, // movw %ax,%ds 0x8e, 0xc0, // movw %ax,%es 0x8e, 0xd0, // movw %ax,%ss 0x0f, 0x01, 0x16, 0x44, 0x7c, // lgdt gdtdesc 0x0f, 0x20, 0xc0, // movl %cr0,%eax 0x66, 0x83, 0xc8, 0x01, // orl $CR0_PE,%eax 0x0f, 0x22, 0xc0, // movl %eax,%cr0 0xea, 0x1d, 0x7c, 0x08, 0x00, // ljmp $GDT_ENTRY(1),$start32 // start32: 0x66, 0xb8, 0x10, 0x00, // movw $0x10,%ax 0x8e, 0xd8, // movw %ax, %ds 0x8e, 0xc0, // movw %ax, %es 0x8e, 0xd0, // movw %ax, %ss 0xeb, 0xfe, // jmp 7c27 0x8d, 0x76, 0x00, // lea 0x0(%esi),%esi // GDT 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x9a, 0xcf, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x92, 0xcf, 0x00, // GDT descriptor 0x17, 0x00, 0x2c, 0x7c, 0x00, 0x00 }; void init_isa() { // put the MBR code to QEMU to enable protected mode bool ok = gdb_memcpy_to_qemu(0x7c00, mbr, sizeof(mbr)); assert(ok == 1); union isa_gdb_regs r; gdb_getregs(&r); // set cs:eip to 0000:7c00 r.eip = 0x7c00; r.cs = 0x0000; ok = gdb_setregs(&r); assert(ok == 1); // execute enough instructions to enter protected mode difftest_exec(20); } #else void init_isa() { } #endif