Verified Commit 5b7e3ec2 authored by SIMONIN Matthieu's avatar SIMONIN Matthieu
Browse files

update links

parent 54eda33b
Pipeline #153914 failed with stages
in 3 minutes and 39 seconds
......@@ -8,16 +8,16 @@
- Question: What happens when the guest want to output a network packet ?
- MMIO: https://en.wikipedia.org/wiki/Memory-mapped_I%2FO
- MMIO: [[https://en.wikipedia.org/wiki/Memory-mapped_I%2FO]]
- Initialisation
When the device is initialised it declares a MMIO region which is a special
Memory Region with callbacks associated for ~read~ and ~write~ operation.
+ For e1000 emulated card this is found here: https://github.com/qemu/qemu/blob/v4.2.0/hw/net/e1000.c#L1626-L1642
+ The MMIO region is built with this options: https://github.com/qemu/qemu/blob/v4.2.0/hw/net/e1000.c#L1342-L1350
+ For e1000 emulated card this is found here: [[https://github.com/qemu/qemu/blob/v4.2.0/hw/net/e1000.c#L1626-L1642]]
+ The MMIO region is built with this options: [[https://github.com/qemu/qemu/blob/v4.2.0/hw/net/e1000.c#L1342-L1350]]
+ ~e1000_mmio_write~ will be responsible to send the network packet to its associated peer (here the tap backend)
- following some calls, e1000 ends up calling ~qemu_send_packet~, the generic function to transfer data between peers (here frontend -> backend): https://github.com/qemu/qemu/blob/v4.2.0/hw/net/e1000.c#L552
- following some calls, e1000 ends up calling ~qemu_send_packet~, the generic function to transfer data between peers (here frontend -> backend): [[https://github.com/qemu/qemu/blob/v4.2.0/hw/net/e1000.c#L552]]
- Runtime: how/when the ~read/write~ callbacks are actually called ?
+ that's easy to answer tracing the callers: ~read/write~ callbacks are called by ~memory_dispatch_read/write~ and ~io_readx/io_writex~ in ~cputlb.c~
......@@ -31,44 +31,44 @@
+ Qemu translates the guest instructions to host understandable instructions in 2 phases:
- first it translates the guest instruction into instructions of an intermediate instruction set: TCG (Tiny Code Generation)
- second it translates the TCG instruction into instruction executable by the host
Réf: https://github.com/qemu/qemu/blob/v4.2.0/docs/devel/tcg.rst
Réf: [[https://github.com/qemu/qemu/blob/v4.2.0/docs/devel/tcg.rst]]
- translation occurs in the emulated CPU routine.
an emulated CPU will (almost) continuously -- https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/cpu-exec.c#L715
+ get the next sets of instruction to translate and translate it to TCG -- https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/translate-all.c#L1734
+ then translate it to the target host instruction sets -- https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/translate-all.c#L1757
+ and execute it -- https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/cpu-exec.c#L731
+ First phase: Guest to TCG -- (actually depends on the guest implementation) https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/translate-all.c#L1734
an emulated CPU will (almost) continuously -- [[https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/cpu-exec.c#L715]]
+ get the next sets of instruction to translate and translate it to TCG -- [[https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/translate-all.c#L1734]]
+ then translate it to the target host instruction sets -- [[https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/translate-all.c#L1757]]
+ and execute it -- [[https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/cpu-exec.c#L731]]
+ First phase: Guest to TCG -- (actually depends on the guest implementation) [[https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/translate-all.c#L1734]]
- instructions are translated by block of instructions: ~Translation Block (tb)~. Each tb is
translated one after the another.
- a ~Tb~ in qemu stores some some meta
data about the translated instructions (e.g the program counter of the
current block, the address of the next instruction of the next Tb [e.g to
jump directly to the next Tb code]) -- https://github.com/qemu/qemu/blob/v4.2.0/include/exec/exec-all.h#L366-L433
- there's a cache mecanism that caches Tbs -- https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/cpu-exec.c#L403-L410
jump directly to the next Tb code]) -- [[https://github.com/qemu/qemu/blob/v4.2.0/include/exec/exec-all.h#L366-L433]]
- there's a cache mecanism that caches Tbs -- [[https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/cpu-exec.c#L403-L410]]
- guest instructions are translated one after another.
+ depends on the guest arch: e.g for i386 -- https://github.com/qemu/qemu/blob/v4.2.0/target/i386/translate.c#L4486
+ depends on the guest arch: e.g for i386 -- [[https://github.com/qemu/qemu/blob/v4.2.0/target/i386/translate.c#L4486]]
- e.g for ~inc~ instruction
+ https://en.wikipedia.org/wiki/X86_instruction_listings
+ https://github.com/qemu/qemu/blob/v4.2.0/target/i386/translate.c#L4773-L4776
+ [[https://en.wikipedia.org/wiki/X86_instruction_listings]]
+ [[https://github.com/qemu/qemu/blob/v4.2.0/target/i386/translate.c#L4773-L4776]]
- One interesting aspect is that for memory access TCG uses load/store instructions
+ e.g for inc if the operant is a memory address it is detected and special load instruction is generated (instead of a move)
+ instruction for loading the operand (address in this case) is generated here: https://github.com/qemu/qemu/blob/v4.2.0/target/i386/translate.c#L1413
+ instruction for storing the operand (address in this case) is generated here: https://github.com/qemu/qemu/blob/v4.2.0/target/i386/translate.c#L439
+ Second phase: TCG to Host -- https://github.com/qemu/qemu/blob/v4.2.0/tcg/tcg.c#L4013
- ~tcg_gen_code~ go through all the TCG instructions -- https://github.com/qemu/qemu/blob/v4.2.0/tcg/tcg.c#L4131-L4138
+ instruction for loading the operand (address in this case) is generated here: [[https://github.com/qemu/qemu/blob/v4.2.0/target/i386/translate.c#L1413]]
+ instruction for storing the operand (address in this case) is generated here: [[https://github.com/qemu/qemu/blob/v4.2.0/target/i386/translate.c#L439]]
+ Second phase: TCG to Host -- [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/tcg.c#L4013]]
- ~tcg_gen_code~ go through all the TCG instructions -- [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/tcg.c#L4131-L4138]]
- But now we have special ld/st instruction when memory is accessed.
this code is specific to the host arch. For i386: https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L2255
for ld/st instruction -- https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L2527-L2538
opcode are macro generated by: https://github.com/qemu/qemu/blob/v4.2.0/tcg/tcg-opc.h#L52-L59
this code is specific to the host arch. For i386: [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L2255]]
for ld/st instruction -- [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L2527-L2538]]
opcode are macro generated by: [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/tcg-opc.h#L52-L59]]
- For load/store opcode, qemu relies on a tlb to do guest to host address translation and proceed with the operations
+ e.g for ld instruction: https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L2122-L2130
+ the host address from the TLB are generated: https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L1699
+ if a cache miss occurs (at the execution time (not now)) qemu generate a conditional jump: https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L1759-L1761
+ e.g for ld instruction: [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L2122-L2130]]
+ the host address from the TLB are generated: [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L1699]]
+ if a cache miss occurs (at the execution time (not now)) qemu generate a conditional jump: [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L1759-L1761]]
- When all the TCG instructions are generated, Qemu generates all the slow path blocks (needed in cas of cache miss)
+ here -- https://github.com/qemu/qemu/blob/v4.2.0/tcg/tcg.c#L4209
+ for i386/ld op: https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L1810
+ and here ... is the magic ... it generate a call to a c helper function: https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L1850
- ld/store helper calls ~io_readx~/~io_writex~ if the ~tlb_addr~ is flagged as an MMIO region: e.g https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/cputlb.c#L1715-L1718
+ here -- [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/tcg.c#L4209]]
+ for i386/ld op: [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L1810]]
+ and here ... is the magic ... it generate a call to a c helper function: [[https://github.com/qemu/qemu/blob/v4.2.0/tcg/i386/tcg-target.inc.c#L1850]]
- ld/store helper calls ~io_readx~/~io_writex~ if the ~tlb_addr~ is flagged as an MMIO region: e.g [[https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/cputlb.c#L1715-L1718]]
- TODO who's flagging the ~tlb_addr~ as MMIO ?
......@@ -81,17 +81,17 @@
+ ~tap_send~ (after some indirection) call the ~receive~ method of the network frontend (the ~e1000~ emulated NIC)
-> ~e1000.c:e1000_receive_iov~
+ the network card has now the packet and uses DMA to write it somewhere in RAM
- calls ~pci_dma_write~ -- https://github.com/qemu/qemu/blob/v4.2.0/hw/net/e1000.c#L968
- This function eventually write in RAM the incoming packet: -- https://github.com/qemu/qemu/blob/v4.2.0/exec.c#L3132-L3135
- calls ~pci_dma_write~ -- [[https://github.com/qemu/qemu/blob/v4.2.0/hw/net/e1000.c#L968]]
- This function eventually write in RAM the incoming packet: -- [[https://github.com/qemu/qemu/blob/v4.2.0/exec.c#L3132-L3135]]
(au passage cela va invalider tous les TB qui utiliserait les pages concernés.)
- ~e1000~ sets an interruption -- https://github.com/qemu/qemu/blob/v4.2.0/hw/net/e1000.c#L1013
- ~e1000~ sets an interruption -- [[https://github.com/qemu/qemu/blob/v4.2.0/hw/net/e1000.c#L1013]]
+ TODO: understand why it will be seen by the CPU on the next loop.
- the interruption flows until reaching the CPU ( though pci and i8259 PIC)
- CPU hardware interruption in QEMU
+ in between two TB executions the CPU check the interruption status -- https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/cpu-exec.c#L715
+ cpu interruption routine is deferred to a specific harware (e.g x86) -- https://github.com/qemu/qemu/blob/v4.2.0/target/i386/cpu.c#L7061
+ which filter the interruption source (e.g hardware) -- https://github.com/qemu/qemu/blob/v4.2.0/target/i386/seg_helper.c#L1357-L1365
+ finally look up on the Interruption Table Descriptor to find the (kernel) interruption handler to call -- [[https://github.com/qemu/qemu/blob/v4.2.0/target/i386/seg_helper.c#L872-L879]]
+ in between two TB executions the CPU check the interruption status -- [[https://github.com/qemu/qemu/blob/v4.2.0/accel/tcg/cpu-exec.c#L715]]
+ cpu interruption routine is deferred to a specific harware (e.g x86) -- [[https://github.com/qemu/qemu/blob/v4.2.0/target/i386/cpu.c#L7061]]
+ which filter the interruption source (e.g hardware) -- [[https://github.com/qemu/qemu/blob/v4.2.0/target/i386/seg_helper.c#L1357-L1365]]
+ finally look up on the Interruption Table Descriptor to find the (kernel) interruption handler to call -- [[[[https://github.com/qemu/qemu/blob/v4.2.0/target/i386/seg_helper.c#L872-L879]]]]
+ TODO: understand how/when the packet is actually read by the guest driver (when the interruption handler is called ?)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment