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
+
+
+* mipsivm runs CSE3666 Lab 2
+
+
## 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