The Android Open Source Project | 92c7311 | 2009-03-05 14:34:31 -0800 | [diff] [blame] | 1 | HOW THE QEMU EXECUTION ENGINE WORKS: |
| 2 | ==================================== |
| 3 | |
| 4 | Translating ARM to x86 machine code: |
| 5 | ------------------------------------ |
| 6 | |
| 7 | QEMU starts by isolating code "fragments" from the emulated machine code. |
The Android Open Source Project | b059fac | 2009-03-11 12:11:56 -0700 | [diff] [blame] | 8 | Each "fragment" corresponds to a series of ARM instructions ending with a |
The Android Open Source Project | 92c7311 | 2009-03-05 14:34:31 -0800 | [diff] [blame] | 9 | branch (e.g. jumps, conditional branches, returns). |
| 10 | |
| 11 | Each fragment is translated into a "translated block" (a.k.a. TB) of host |
| 12 | machine code (e.g. x86). All TBs are put in a cache and each time the |
| 13 | instruction pointer changes (i.e. at the end of TB execution), a hash |
| 14 | table lookup is performed to find the next TB to execute. |
| 15 | |
| 16 | If none exists, a new one is generated. As a special exception, it is |
| 17 | sometimes possible to 'link' the end of a given TB to the start of |
| 18 | another one by tacking an explicit jump instruction. |
| 19 | |
| 20 | Note that due to differences in translations of memory-related operations |
| 21 | (described below in "MMU emulation"), there are actually two TB caches per |
| 22 | emulated CPU: one for translated kernel code, and one for translated |
| 23 | user-space code. |
| 24 | |
| 25 | When a cache fills up, it is simply totally emptied and translation starts |
| 26 | again. |
| 27 | |
| 28 | CPU state is kept in a single global structure which the generated code |
| 29 | can access directly (with direct memory addressing). |
| 30 | |
The Android Open Source Project | b059fac | 2009-03-11 12:11:56 -0700 | [diff] [blame] | 31 | The file target-arm/translate.c is in charge of translating the ARM or |
The Android Open Source Project | 92c7311 | 2009-03-05 14:34:31 -0800 | [diff] [blame] | 32 | Thumb instructions starting at the current instruction pointer position |
| 33 | into a TB. This is done by decomposing each instruction into a series of |
| 34 | micro-operations supported by the TCG code generator. |
| 35 | |
| 36 | TCG stands for "Tiny Code Generator" and is specific to QEMU. It supports |
| 37 | several host machine code backends. See source files under tcg/ for details. |
| 38 | |
| 39 | |
| 40 | MMU Emulation: |
| 41 | -------------- |
| 42 | |
| 43 | The ARM Memory Management Unit is emulated in software, since it is so |
| 44 | different from the one on the host. Essentially, a single ARM memory load/store |
| 45 | instruction is translated into a series of host machine instructions that will |
| 46 | translate virtual addresses into physical ones by performing the following: |
| 47 | |
| 48 | - first lookup in a global 256-entries cache for the current page and see if |
| 49 | a corresponding value is already stored there. If this is the case, use it |
| 50 | directly. |
| 51 | |
| 52 | - otherwise, call a special helper function that will implement the full |
| 53 | translation according to the emulated system's state, and modify the |
| 54 | cache accordingly. |
| 55 | |
| 56 | The page cache is called the "TLB" in the QEMU sources. |
| 57 | |
| 58 | Note that there are actually two TLBs: one is used for host machine |
| 59 | instructions that correspond to kernel code, and the other for instructions |
| 60 | translated from user-level code. |
| 61 | |
| 62 | This means that a memory load in the kernel will not be translated into the |
| 63 | same instructions than the same load in user space. |
| 64 | |
The Android Open Source Project | b059fac | 2009-03-11 12:11:56 -0700 | [diff] [blame] | 65 | Each TLB is also implemented as a global per-emulated-CPU hash-table. |
| 66 | The user-level TLB is flushed on each process context switch. |
The Android Open Source Project | 92c7311 | 2009-03-05 14:34:31 -0800 | [diff] [blame] | 67 | |
| 68 | When initializing the MMU emulation, one can define several zones of the |
| 69 | address space, with different access rights / type. This is how memory-mapped |
The Android Open Source Project | b059fac | 2009-03-11 12:11:56 -0700 | [diff] [blame] | 70 | I/O is implemented: the virtual->physical conversion helper function detects |
| 71 | that you're trying to read/write from an I/O memory region, and will then call |
The Android Open Source Project | 92c7311 | 2009-03-05 14:34:31 -0800 | [diff] [blame] | 72 | a callback function associated to it. |
| 73 | |
| 74 | |
| 75 | Hardware Emulation: |
| 76 | ------------------- |
| 77 | |
| 78 | Most hardware emulation code initializes by registering its own region of |
The Android Open Source Project | b059fac | 2009-03-11 12:11:56 -0700 | [diff] [blame] | 79 | I/O memory, as well as providing read/write callbacks for it. Then actions |
| 80 | will be based on which offset of the I/O memory is read from/written to and |
The Android Open Source Project | 92c7311 | 2009-03-05 14:34:31 -0800 | [diff] [blame] | 81 | eventually with which value. |
| 82 | |
David 'Digit' Turner | 6ba28da | 2014-01-10 12:21:19 +0100 | [diff] [blame] | 83 | You can have a look at hw/android/goldfish/tty.c that implements an |
| 84 | emulated serial port for the Goldfish platform. |
The Android Open Source Project | 92c7311 | 2009-03-05 14:34:31 -0800 | [diff] [blame] | 85 | |
| 86 | "Goldfish" is simply the name of the virtual Linux platform used to build |
| 87 | the Android-emulator-specific kernel image. The corresponding sources are |
SeongJae Park | 9849988 | 2013-03-26 11:35:47 +0900 | [diff] [blame] | 88 | located in the origin/android-goldfish-2.6.29 branch of |
| 89 | https://android.googlesource.com/kernel/goldfish.git. You can have a look at |
The Android Open Source Project | 92c7311 | 2009-03-05 14:34:31 -0800 | [diff] [blame] | 90 | arch/arm/mach-goldfish/ for the corresponding kernel driver sources. |
| 91 | |