This section contains some examples of how to inspect processors and devices, when running the qsp-x86/firststeps target machine.
Launch the simulator with the qsp-x86/firststeps target.
$ ./simics qsp-x86/firststeps
To inspect the target machine, use the list-objects command.
simics> list-objects -local
┌───────────────┬───────────────────┐
│ Object │ Component Class │
├───────────────┼───────────────────┤
│board │<chassis_qsp_x86> │
│ethernet_switch│<ethernet_switch> │
│service_node │<service_node_comp>│
└───────────────┴───────────────────┘
┌───────────────────┬───────────────┐
│ Object │ Class │
├───────────────────┼───────────────┤
│bp │<bp-manager> │
│default_sync_domain│<sync_domain> │
│params │<script-params>│
│prefs │<preferences> │
│sim │<sim> │
└───────────────────┴───────────────┘
Here we see that we have a few special objects, like the breakpoint manager and the sim object, we have the network related objects, and at the top we have the actual machine. We can look at the objects inside it:
simics> list-objects namespace = board -local
┌────────────────┬───────────────────────┐
│ Object │ Component Class │
├────────────────┼───────────────────────┤
│board.console │<gfx_console_comp> │
│board.disk0 │<sata_disk_comp> │
│board.disk1 │<sata_disk_comp> │
│board.mb │<motherboard_x58_ich10>│
│board.serconsole│<txt_console_comp> │
│board.usb_disk │<usb_disk_comp> │
└────────────────┴───────────────────────┘
┌──────────────────┬──────────────┐
│ Object │ Class │
├──────────────────┼──────────────┤
│board.cell │<cell> │
│board.cell_context│<context> │
│board.cell_rec0 │<recorder> │
│board.software │<os_awareness>│
└──────────────────┴──────────────┘
To see the objects associated with the processor, we can again use the list-objects command. The -tree option displays the objects in a hierarchical fashion.
simics> list-objects -show-port-objects namespace = board.mb.cpu0 -tree
┐
├ apic[0] ┐
│ └ [0] ┐
│ ├ bank ┐
│ │ └ apic_regs
│ └ port ┐
│ └ freq_listener
├ core[0] ┐
│ └ [0] ┐
│ ├ probes ┐
│ │ └ uncore
│ └ vtime ┐
│ ├ cycles
│ └ ps
├ mem[0] ┐
│ └ [0]
├ socket
└ tlb[0] ┐
└ [0]
To list all processors, use the list-processors command.
Note the * to the right of board.mb.cpu0.core[0][0] and the last line * = selected CPU.
In this system, there is only one processor, but in systems with multiple processors,
the command pselect can be used to get the current processor or select
another processor.
More on this here.
simics> list-processors
┌────────────────────────┬─┬─────────┬────────┐
│ CPU Name │ │CPU Class│ Freq │
├────────────────────────┼─┼─────────┼────────┤
│board.mb.cpu0.core[0][0]│*│x86QSP1 │2.00 GHz│
└────────────────────────┴─┴─────────┴────────┘
* = selected CPU
The list-processors command can show information about the state of each processor core, to help diagnose the current state of the system. There are multiple switches available, use help or tab-completion to see the available options. The -disassemble option is particularly interesting, as it often indicates processor modes like wait states.
simics> list-processors -disassemble
┌────────────────────────┬─┬─────────┬────────┬────────────────────────┐
│ CPU Name │ │CPU Class│ Freq │ Disassembly │
├────────────────────────┼─┼─────────┼────────┼────────────────────────┤
│board.mb.cpu0.core[0][0]│*│x86QSP1 │2.00 GHz│cs:0x000000000000fff0 p:│
│ │ │ │ │0x0fffffff0 nop │
└────────────────────────┴─┴─────────┴────────┴────────────────────────┘
The current processor (marked with a * in list-processors)
is used by some global commands, for example in print-processor-registers,
as the processor the command operates to.
To access the current processor, use the cpu object alias.
The cpu object alias can be used both to get the current processor, and
to tab-expand commands, child objects and attributes of the current processor.
simics> cpu
"board.mb.cpu0.core[0][0]"
simics> cpu # press tab twice to expand everything starting with cpu
cpu-> cpu-pages-dump cpu-switch-time cpu. cpu.vtime.
simics> cpu. # press tab twice to expand child objects and commands
cpu.aprof-views cpu.instruction-fetch-mode
cpu.bp-break-control-register cpu.instrumentation-move
cpu.bp-break-cycle cpu.instrumentation-order
...
simics> cpu-> # press tab twice to expand attributes
cpu->a20_inhibited
cpu->a20mask
cpu->access_count
cpu->access_type_name
cpu->activity_state
...
To change the current processor, use the command pselect. Without argument this shows
the current processor, just like cpu.
simics> pselect "board.mb.cpu0.core[0][0]"
simics> pselect
"board.mb.cpu0.core[0][0]"
We can inspect the registers and current execution mode of a processor by using the print-processor-registers command.
simics> board.mb.cpu0.core[0][0].print-processor-registers
16-bit legacy real mode
rax = 0x0000000000000000 r8 = 0x0000000000000000
rcx = 0x0000000000000000 r9 = 0x0000000000000000
rdx = 0x00000000000106a1 r10 = 0x0000000000000000
rbx = 0x0000000000000000 r11 = 0x0000000000000000
rsp = 0x0000000000000000 r12 = 0x0000000000000000
rbp = 0x0000000000000000 r13 = 0x0000000000000000
rsi = 0x0000000000000000 r14 = 0x0000000000000000
rdi = 0x0000000000000000 r15 = 0x0000000000000000
rip = 0x000000000000fff0
eflags = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 = 0x00000002
I V V A V R - N I I O D I T S Z - A - P - C
D I I C M F T O O F F F F F F F F F
P F P P
L L
Another way to read registers of the current processor (see here)
would be to run the global command print-processor-registers.
simics> print-processor-registers
Individual registers are also typically accessible. Here we also use the output-radix command that specifies the base when numbers are displayed.
simics> output-radix 16
simics> %rdx
0x106a1
We can also inspect devices, their register banks, and individual registers. Information about their registers can be displayed using the print-device-regs command. For example, we can look at the DMI device. First, we locate it in the system.
simics> list-classes -l substr = dmi -show-port-classes
The following classes have been registered:
┌───────────────────┬──────────────────────────────────────────────────┐
│ Class │ Short description │
├───────────────────┼──────────────────────────────────────────────────┤
│x58-dmi │Intel® X58 DMI unit │
│x58-dmi.HRESET │ │
│x58-dmi.io_regs │ │
│x58-dmi.msg │legacy PCI INTx message to pci_interrupt converter│
│x58-dmi.pcie_config│ │
│x58-dmi.phy │ │
└───────────────────┴──────────────────────────────────────────────────┘
simics> list-objects class = x58-dmi -all
┌──────────────────┬─────────┐
│ Object │ Class │
├──────────────────┼─────────┤
│board.mb.nb.bridge│<x58-dmi>│
└──────────────────┴─────────┘
Now we can inspect the banks and device registers.
simics> print-device-regs bank = board.mb.nb.bridge
Bank: io_regs
┌──────┬──────────────┬────┬─────┐
│Offset│ Name │Size│Value│
├──────┼──────────────┼────┼─────┤
│ 0xcf8│config_address│ 0x4│ 0x0│
│ 0xcfc│config_data │ 0x4│ 0x0│
└──────┴──────────────┴────┴─────┘
Bank: pcie_config
┌──────┬───────────────────┬────┬───────┐
│Offset│ Name │Size│ Value │
├──────┼───────────────────┼────┼───────┤
│ 0xcf8│config_address │ 0x4│ 0x0│
│ 0xcfc│config_data │ 0x4│ 0x0│
│ 0x0│vendor_id │ 0x2│ 0x8086│
│ 0x2│device_id │ 0x2│ 0x3400│
│ 0x4│command │ 0x2│ 0x0│
│ 0x6│status │ 0x2│ 0x10│
│ 0x8│revision_id │ 0x1│ 0x13│
│ 0x9│class_code │ 0x3│0x80000│
│ 0xc│cache_line_size │ 0x1│ 0x0│
│ 0xd│latency_timer │ 0x1│ 0x0│
│ 0xe│header_type │ 0x1│ 0x0│
│ 0xf│bist │ 0x1│ 0x0│
│ 0x2c│subsystem_vendor_id│ 0x2│ 0x8086│
│ 0x2e│subsystem_id │ 0x2│ 0x0│
│ 0x34│capabilities_ptr │ 0x1│ 0x0│
│ 0x3c│interrupt_line │ 0x1│ 0x0│
│ 0x3d│interrupt_pin │ 0x1│ 0x0│
└──────┴───────────────────┴────┴───────┘
We can specify a pattern to only display certain registers.
simics> print-device-regs bank = board.mb.nb.bridge pattern = vendor_id
Bank: pcie_config
┌──────┬─────────┬────┬──────┐
│Offset│ Name │Size│Value │
├──────┼─────────┼────┼──────┤
│ 0x0│vendor_id│ 0x2│0x8086│
└──────┴─────────┴────┴──────┘
To obtain more information about a particular register, we can use the print-device-reg-info command.
simics> print-device-reg-info register = board.mb.nb.bridge.bank.pcie_config.vendor_id
Vendor ID [board.mb.nb.bridge.bank.pcie_config.vendor_id]
Bits : 0x10
Offset : 0x0
Value : 0x8086
----------
Bit Fields
vendor_id @ [15:0] : 1000000010000110
When retrieving a register value for inspection or use in further code, it is better to use one of the commands designed for that purpose:
get-device-regget-device-offsetread-device-regread-device-offsetset-device-regset-device-offsetwrite-device-regwrite-device-offsetThe command names have the following meanings:
Operation type:
Target specification:
simics> get-device-reg board.mb.nb.bridge.bank.pcie_config.device_id
0x3400
simics> get-device-offset board.mb.nb.bridge.bank.pcie_config offset = 2 size = 2
0x3400
To sum up, we have shown a few simple ways in which the hardware can be inspected. One important point is that the inspection is non-intrusive, any software running on the target machine cannot notice anything of our inspection.