diff --git a/README.md b/README.md index ac5a9f1..ee3c558 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,13 @@ # mipsivm The name of the project "mipsivm" is an abbreviation for "MIPS Interpreting Virtual Machine". +## Showcase +* mipsivm runs Hello World +![Showcase Hello World](test/mipsivm_show_helloworld.JPG) + +* mipsivm runs CSE3666 Lab 2 +![Showcase CSE3666 Lab2](test/mipsivm_show_lab2.JPG) + ## Introduction The "mipsivm" is a software-based Emulator project aiming to virtualize the minimum MIPS-based machine and efficient virtualized memory.
This project is an interpreting emulator project - providing the accurate emulation. @@ -14,14 +21,15 @@ To virtualize the processor, we implement the VMCB structure. VMCB is the acrony Duly note that mipsivm simulates in LE byte order. ### Glossary of Processor Virtualization -| Acronyms | Abbreviated for | Explanation | -| --------- | ----------------------------- | --------------------------------- | -| vCPU | Virtual CPU | The virtual processor | -| FPU | Floating Processing Unit | Co-processor for floating number | -| RF | Register File | Storage of Registers | -| GPR | General Purpose Register | Register of CPU | -| VMCB | Virtual Machine Control Block | Controlling Structure for a vCPU | -| MPT | MIPS Page Table | Address of Root of Paging | +| Acronyms | Abbreviated for | Explanation | +| --------- | ----------------------------- | ------------------------------------- | +| vCPU | Virtual CPU | The virtual processor | +| FPU | Floating Processing Unit | Co-processor for floating number | +| RF | Register File | Storage of Registers | +| GPR | General Purpose Register | Register of CPU | +| VMCB | Virtual Machine Control Block | Controlling Structure for a vCPU | +| NPT | Nested Page Table | Page Table that translates GPA to HVA | +| MPT | MIPS Page Table | Page Table that translates GVA to GPA | ## Memory Virtualization The memory virtualization is the special feature of the project. This project uses paging as inspired by AMD64 architecture.
@@ -66,7 +74,7 @@ Each PTE is an 8-byte entry. There are 512 PTEs. For each entry, there are 64 bi ## FAQ Following lists the frequently asked questions, and corresponding answers. -### Why the Project? +### Why did I create this project? In my sophomore year, I took the CSE3666 course - Introduction to Computer Architecture. In the final month of the semester, there is an emulator project - emulate an MIPS machine. The emulator skeleton is in either python or java implemention. I considered the implementation is not quite efficient. So this project is given birth by me - implement the emulator in an efficient interpreting method. ### Is there a well-known open-source MIPS emulator project? @@ -80,7 +88,7 @@ Yes, there is. The famous PCSX2 is a free and open-source PlayStation 2 (PS2) em - This project is designed to support multiple presets for simulation. With different preset, mipsivm may support multi-processing system. ## Build -If it is your first time to build mipsivm, you will have execute `build_prep.bat` script file to prepare for compilation prior to execute any build scripts.
+If it is your first time to build mipsivm, you will have to execute `build_prep.bat` script file to prepare for compilation prior to execute any build scripts.
Currently, mipsivm supports 64-bit Windows. ### Windows @@ -108,7 +116,7 @@ Here list command-line arguments specific to MARS Runtime Preset. ``` mipsivm /nologo /runtime mars /ds helloworld.data.bin /ts helloworld.text.bin ``` -This code would suppress the logo printer then load `helloworld.data.bin` as `.data` section and `helloworld.text.bin` as `.text` section of the program, with 64KiB stack, and run the program. +This code would suppress the logo printer then load `helloworld.data.bin` as `.data` section and `helloworld.text.bin` as `.text` section of the program, with 64KiB default stack, and run the program. ## License This repository is licensed under the MIT license. \ No newline at end of file diff --git a/MIPS_Green_Sheet.pdf b/ref/MIPS_Green_Sheet.pdf similarity index 100% rename from MIPS_Green_Sheet.pdf rename to ref/MIPS_Green_Sheet.pdf diff --git a/ref/mips-isa.pdf b/ref/mips-isa.pdf new file mode 100644 index 0000000..fc93d81 Binary files /dev/null and b/ref/mips-isa.pdf differ diff --git a/src/entry.c b/src/entry.c index dafcb98..d1862b4 100644 --- a/src/entry.c +++ b/src/entry.c @@ -150,6 +150,7 @@ int main(int argc,char* argv[],char* envp[]) } puts("MARS Environment is initialized successfully!"); mips_run_mars_vm(); + mips_final_mars_vm(); mars_final: unload_section(ds_ptr); unload_section(ts_ptr); diff --git a/src/include/devkit.h b/src/include/devkit.h index 3b9bffb..d2d778e 100644 --- a/src/include/devkit.h +++ b/src/include/devkit.h @@ -19,6 +19,7 @@ bool mips_init_mars_vm(void* ds,void* ts,u32 ds_size,u32 ts_size,u32 stack_size); void mips_run_mars_vm(); +void mips_final_mars_vm(); void cdecl sim_printf(const char* format,...); i32 sim_readint(); @@ -29,6 +30,7 @@ char sim_readchar(); void sim_setseed(u32 seed); u32 sim_getrand(); +void report_memory_introspection(); void* load_section(char* file_path,u32* size); bool unload_section(void* section); void* alloc_page(u32 size); diff --git a/src/include/mipsdef.h b/src/include/mipsdef.h index 5623f98..1ef90ae 100644 --- a/src/include/mipsdef.h +++ b/src/include/mipsdef.h @@ -233,8 +233,8 @@ char* mips_cpu_opcode_string[64]= null, // 0x13 null, // 0x14 null, // 0x15 - null, // 0x16 - null, // 0x17 + "blezl", // 0x16 + "bgtzl", // 0x17 null, // 0x18 null, // 0x19 null, // 0x1A @@ -250,7 +250,7 @@ char* mips_cpu_opcode_string[64]= "lbu", // 0x24 "lhu", // 0x25 "lwr", // 0x26 - null, // 0x27 + "lwu", // 0x27 "sb", // 0x28 "sh", // 0x29 "swl", // 0x2A @@ -277,6 +277,42 @@ char* mips_cpu_opcode_string[64]= null // 0x3F }; +char* mips_cpu_regimm_string[32]= +{ + "bltz", // 0x00 + "bgez", // 0x01 + "bltzl", // 0x02 + "bgezl", // 0x03 + null, // 0x04 + null, // 0x05 + null, // 0x06 + null, // 0x07 + "tgei", // 0x08 + "tgeiu", // 0x09 + "tlti", // 0x0A + "tltiu", // 0x0B + "teqi", // 0x0C + null, // 0x0D + "tnei", // 0x0E + null, // 0x0F + "bltzal", // 0x10 + "bgezal", // 0x11 + "bltzall", // 0x12 + "bgezall", // 0x13 + null, // 0x14 + null, // 0x15 + null, // 0x16 + null, // 0x17 + null, // 0x18 + null, // 0x19 + null, // 0x1A + null, // 0x1B + null, // 0x1C + null, // 0x1D + null, // 0x1E + null // 0x1F +} + char* mips_cpu_funct_string[64]= { "sll", // 0x00 diff --git a/src/include/vmcb.h b/src/include/vmcb.h index 837e104..61bc7cc 100644 --- a/src/include/vmcb.h +++ b/src/include/vmcb.h @@ -151,7 +151,7 @@ typedef struct _vmcb #else l2p_pde_p npt_base; // Points to 512 Entries of PDE #endif - u64 tsc; // Time-Stamp Counter, aka TSC, Processor Ticks. + u64 tsc; // Guest Time-Stamp Counter, aka TSC, Processor Ticks. u64 eic; // Executed Instruction Counter. u32 vm_type; }vmcb,*vmcb_p; @@ -177,6 +177,7 @@ typedef struct _mips_mars_vm void* mips_ref_hmem(vmcb_p vcpu,u32 gpa,bool r,bool w,bool x); bool mips_npt_edit_entry(vmcb_p vcpu,u32 gpa,void* hva,bool r,bool w,bool x); +void mips_npt_cleanup(vmcb_p vcpu); void mips_vcpu_start_interpretation(vmcb_p vcpu); void mips_vcpu_dump_state(vmcb_p vcpu); diff --git a/src/mars.c b/src/mars.c index 78f86c1..61b95e5 100644 --- a/src/mars.c +++ b/src/mars.c @@ -193,4 +193,11 @@ void mips_run_mars_vm() ghr=(double)vm.vcpu.tsc/(double)tsc_diff; sim_printf("Guest/Host TSC Rate: %f (Higher TSC Rate indicates better simulation performance)\n",ghr); mips_vcpu_dump_state(&vm.vcpu); +} + +void mips_final_mars_vm() +{ + free_page(vm.stack.address); + mips_npt_cleanup(&vm.vcpu); + report_memory_introspection(); } \ No newline at end of file diff --git a/src/vcpu.c b/src/vcpu.c index 6de8684..d0c312a 100644 --- a/src/vcpu.c +++ b/src/vcpu.c @@ -74,6 +74,28 @@ bool mips_npt_edit_entry(vmcb_p vcpu,u32 gpa,void* hva,bool r,bool w,bool x) #endif } +void mips_npt_cleanup(vmcb_p vcpu) +{ +#if defined(_amd64) + u32 i=0; + for(;i<4;i++) + { + l3p_pde_p pdeb=(l3p_pde_p)(vcpu->npt_base[i].pde_page<<12); + if(pdeb) + { + u32 j=0; + for(;j<512;j++) + { + l3p_pte_p pteb=(l3p_pte_p)(pdeb[j].pte_page<<12); + if(pteb)free_page(pteb); + } + free_page(pdeb); + } + } + free_mem(vcpu->npt_base); +#endif +} + void mips_interpreter_unhandled_instruction(vmcb_p vcpu,mips_instruction instruction) { sim_printf("#UD Exception! (Unknown Instruction)\n"); @@ -115,7 +137,7 @@ void mips_vcpu_start_interpretation(vmcb_p vcpu) // Reference HVA by GPA. u32* ip=(u32*)mips_ref_hmem(vcpu,vcpu->gpr.pc,true,false,true); mips_instruction mi; - if(ip==null) // Either the page is not present, or page does not exist. + if(ip==null) // Either the page is not present, or page is not executable. { sim_printf("Nested Page Fault on Execution! pc=0x%08X\n",vcpu->gpr.pc); break; diff --git a/src/xpf/windows/system.c b/src/xpf/windows/system.c index e1475cd..b3dbe3d 100644 --- a/src/xpf/windows/system.c +++ b/src/xpf/windows/system.c @@ -14,6 +14,11 @@ #include +void __cdecl sim_printf(const char* format,...); + +ULONG PageCountAllocated=0; +ULONG HeapCountAllocated=0; + PVOID load_section(IN PSTR FilePath,OUT PULONG Size) { PVOID Buffer=NULL; @@ -49,21 +54,40 @@ BOOL unload_section(IN PVOID SectionAddress) PVOID alloc_page(IN ULONG Size) { PVOID p=VirtualAlloc(NULL,Size,MEM_COMMIT,PAGE_READWRITE); - if(p)RtlZeroMemory(p,Size); + if(p) + { + RtlZeroMemory(p,Size); + PageCountAllocated++; + } return p; } BOOL free_page(IN PVOID Address) { + PageCountAllocated--; return VirtualFree(Address,0,MEM_RELEASE); } PVOID alloc_mem(IN ULONG Size) { - return HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,Size); + PVOID p=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,Size); + if(p)HeapCountAllocated++; + return p; } BOOL free_mem(IN PVOID Address) { + HeapCountAllocated--; return HeapFree(GetProcessHeap(),0,Address); +} + +void report_memory_introspection() +{ + sim_printf("[Memory Introspection] Unreleased Pages: %d\n",PageCountAllocated); + sim_printf("[Memory Introspection] Unreleased Heaps: %d\n",HeapCountAllocated); + if(PageCountAllocated>0 || HeapCountAllocated>0) + sim_printf("[Memory Introspection] Status: there is memory leak!\n"); + else + sim_printf("[Memory Introspection] Status: No memory leak!\n"); + sim_printf("[Memory Introspection] Introspection Completed!\n"); } \ No newline at end of file diff --git a/test/mipsivm_show_helloworld.JPG b/test/mipsivm_show_helloworld.JPG new file mode 100644 index 0000000..6c0c501 Binary files /dev/null and b/test/mipsivm_show_helloworld.JPG differ diff --git a/test/mipsivm_show_lab2.JPG b/test/mipsivm_show_lab2.JPG new file mode 100644 index 0000000..ef2d7f8 Binary files /dev/null and b/test/mipsivm_show_lab2.JPG differ