Skip to content

Commit 38d15d5

Browse files
committed
draft: support for Hexagon VM
Status: boots linux kernel up to setup_command_line() before panic Hacks: * vmnewmap call not implemented (does get invoked by linux) * vmyield call not implemented (does get invoked by linux) * trap0 not quite right (not _yet_ invoked by linux) ... and more Signed-off-by: Brian Cain <[email protected]>
1 parent 2ad908f commit 38d15d5

File tree

16 files changed

+1053
-1
lines changed

16 files changed

+1053
-1
lines changed

docs/system/hexagon/hvm.rst

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
Hexagon Virtual Machine
2+
=======================
3+
4+
The hexagon virtual machine is a hypervisor that can partition a single
5+
Hexagon DSP among multiple guest operating systems, and abstracts the
6+
specific details of a DSP architectural revision for the sake of consistency
7+
among generations.
8+
9+
The ``virt`` machine has Hexagon VM emulation enabled by default.
10+
11+
Events
12+
------
13+
14+
The guest operating system should register the Guest Event Vector Base
15+
via the ``vmsetvec`` virtual instruction at system startup. The vector table
16+
and handlers are determined by the guest OS.
17+
18+
Guests return from event handlers with ``vmrte``. This instruction will restore
19+
the mode (user versus guest), interrupt enable state, PC, SP.
20+
21+
.. list-table:: Event types
22+
:header-rows: 1
23+
24+
* - Number
25+
- Name
26+
- Description
27+
- Maskable
28+
- Detail
29+
* - 0
30+
- Reserved
31+
-
32+
-
33+
-
34+
* - 1
35+
- Machine check event
36+
- unrecoverable VM state
37+
- No
38+
- execution terminates if unhandled
39+
* - 2
40+
- General exception
41+
- internal hardware or software exception
42+
- No
43+
-
44+
* - 3-4
45+
- Reserved
46+
-
47+
-
48+
-
49+
* - 5
50+
- ``trap0``
51+
- ``trap0`` instruction
52+
- No
53+
-
54+
* - 6
55+
- Reserved
56+
-
57+
-
58+
-
59+
* - 7
60+
- Interrupt
61+
- external interrupts
62+
- Yes
63+
- increasing interrupt numbers have descending priority
64+
65+
Startup
66+
-------
67+
In order to transition to user-mode, the guest OS must set the ``UM`` bit in
68+
the guest status register and specify the address to start executing in
69+
user mode in the guest event link register.
70+
71+
Virtual Instructions
72+
--------------------
73+
74+
.. list-table:: Virtual Instructions
75+
:header-rows: 1
76+
77+
* - Instruction
78+
- Behavior
79+
- Operand
80+
- Input
81+
- Output
82+
* - vmversion
83+
- returns the VM version
84+
- 0x0
85+
- requested VM version
86+
- provided VM version
87+
* - vmrte
88+
- return from event
89+
- 0x1
90+
- Event info in g3:0
91+
- N/A
92+
* - vmsetvec
93+
- set event vector
94+
- 0x2
95+
- r0 is set to vector table addr
96+
- r0 is 0 on success, 1 otherwise
97+
* - vmsetie
98+
- set interrupt enabled
99+
- 0x3
100+
- r0 is set to 1 to enable, 0 to disable
101+
- previous IE bit is stored as LSB of r0
102+
* - vmgetie
103+
- get interrupt enabled
104+
- 0x4
105+
- N/A
106+
- current IE bit is stored as LSB of r0
107+
* - vmintop
108+
- interrupt operation
109+
- 0x5
110+
- r0 = Interrupt Op, r1-r4: Depends on Op
111+
- r0 - value depends on operation
112+
* - vmclrmap
113+
- clear virtual memory map
114+
- 0xa
115+
- r0 = Interrupt Op, r1-r4: Depends on Op
116+
- r0 - value depends on operation
117+
* - vmnewmap
118+
- set new virtual memory map
119+
- 0xb
120+
- r0 contains logical address of new segment table, r1 =Type of translations
121+
- r0 contains 0 on success, otherwise negative error code
122+
* - vmcache
123+
- VM cache control: not modeled
124+
- 0xd
125+
- r0 contains the operation to be performed, r1 = Starting virtual address, r2 contains the length in bytes
126+
- r0 contains 0 on success, otherwise -1. Cache behavior is not modeled so this operation always succeeds.
127+
* - vmgettime
128+
- Get virtual machine time
129+
- 0xe
130+
- N/A
131+
- r0 contains the least significant 32 bits of timestamp, r1 contains the most significant 32 bits of timestamp
132+
* - vmsettime
133+
- Set virtual machine time
134+
- 0xf
135+
- r0 contains the least significant 32 bits of timestamp, r1 contains the most significant 32 bits of timestamp
136+
- N/A
137+
* - vmwait
138+
- wait for interrupt
139+
- 0x10
140+
- N/A
141+
- r0 contains the interrupt number of the interrupt waking the guest
142+
* - vmyield
143+
- voluntarily yield VM task
144+
- 0x11
145+
- N/A
146+
- N/A
147+
* - vmstart
148+
- Create new virtual processor instance
149+
- 0x12
150+
- r0 contains the starting execution address, r1 contains the starting stack pointer
151+
- r0 contains the Virtual processor number of new virtual processor on success, otherwise -1
152+
* - vmstop
153+
- terminate current virtual processor instance
154+
- 0x13
155+
- N/A
156+
- N/A
157+
* - vmvpid
158+
- get the virtual processor ID
159+
- 0x14
160+
- N/A
161+
- r0 contains the virtual processor number of virtual processor executing the instruction
162+
* - vmsetregs
163+
- Set guest registers
164+
- 0x15
165+
- r0-3 hold g0-3 values
166+
- N/A
167+
* - vmgetregs
168+
- Get guest registers
169+
- 0x16
170+
- N/A
171+
- r0-3 hold g0-3 values
172+
* - vmtimerop
173+
- perform an operation on a system timer
174+
- 0x18
175+
- getfreq = 0
176+
getres = 1
177+
gettime = 2
178+
gettimeout = 3
179+
settimeout = 4
180+
deltatimeout = 5
181+
- TBD
182+
* - vmgetinfo
183+
- Get system info
184+
- 0x1a
185+
- Index of the system info parameter: FIXME another table
186+
- value of the indicated system info parameter

hw/hexagon/hexagon_testboard.c

+1
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ static void hexagon_common_init(MachineState *machine, Rev_t rev,
180180
CPUHexagonState *env = &cpu->env;
181181
qemu_register_reset(do_cpu_reset, cpu);
182182

183+
qdev_prop_set_bit(DEVICE(cpu), "hexagon-vm", true);
183184
qdev_prop_set_uint32(DEVICE(cpu), "thread-count", machine->smp.cpus);
184185
qdev_prop_set_uint32(DEVICE(cpu), "config-table-addr",
185186
cfgExtensions->cfgbase);

target/hexagon/cpu.c

+7
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ static Property hexagon_cpu_properties[] = {
127127
DEFINE_PROP_BOOL("isdben-dfd-enable", HexagonCPU, isdben_dfd_enable, false),
128128
DEFINE_PROP_BOOL("isdben-trusted", HexagonCPU, isdben_trusted, false),
129129
DEFINE_PROP_BOOL("isdben-secure", HexagonCPU, isdben_secure, false),
130+
DEFINE_PROP_BOOL("hexagon-vm", HexagonCPU, hexagon_vm, false),
130131
DEFINE_PROP_STRING("dump-json-reg-file", HexagonCPU, dump_json_file),
131132
#endif
132133
DEFINE_PROP_UINT32("dsp-rev", HexagonCPU, rev_reg, 0),
@@ -573,11 +574,17 @@ static void hexagon_restore_state_to_opc(CPUState *cs,
573574
#if !defined(CONFIG_USER_ONLY)
574575
void hexagon_cpu_soft_reset(CPUHexagonState *env)
575576
{
577+
CPUState *cs = env_cpu(env);
578+
HexagonCPU *cpu = HEXAGON_CPU(cs);
576579
ARCH_SET_SYSTEM_REG(env, HEX_SREG_SSR, 0);
577580
hexagon_ssr_set_cause(env, HEX_CAUSE_RESET);
578581

579582
target_ulong evb = ARCH_GET_SYSTEM_REG(env, HEX_SREG_EVB);
580583
ARCH_SET_THREAD_REG(env, HEX_REG_PC, evb);
584+
585+
if (cpu->hexagon_vm) {
586+
ARCH_SET_SYSTEM_REG(env, HEX_SREG_IMASK, 0xffffffff);
587+
}
581588
}
582589
#endif
583590

target/hexagon/cpu.h

+1
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ struct ArchCPU {
458458
bool isdben_dfd_enable;
459459
bool isdben_trusted;
460460
bool isdben_secure;
461+
bool hexagon_vm;
461462
#endif
462463
uint32_t rev_reg;
463464
bool lldb_compat;

target/hexagon/gen_tcg.h

+2
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,8 @@
14371437
do { RsV = RsV; } while (0)
14381438
#define fGEN_TCG_Y2_icinva(SHORTCODE) \
14391439
do { RsV = RsV; } while (0)
1440+
#define fGEN_TCG_J2_trap1(SHORTCODE) \
1441+
do { (void) uiV; } while (0)
14401442
#else
14411443
/* data/insn cache ops can raise exceptions */
14421444
#define fGEN_TCG_CACHEOP(HELPER) \

target/hexagon/gen_tcg_sys.h

+5
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,9 @@
135135
tcg_gen_extrh_i64_i32(ctx->t_sreg_new_value[HEX_SREG_SGP1], tmp); \
136136
} while (0)
137137

138+
#define fGEN_TCG_J2_trap1(SHORTCODE) \
139+
do { \
140+
gen_vminst(ctx, uiV); \
141+
} while (0)
142+
138143
#endif

target/hexagon/genptr.c

+98
Original file line numberDiff line numberDiff line change
@@ -1862,5 +1862,103 @@ static void gen_vtcm_memcpy(DisasContext *ctx, TCGv dst, TCGv src, TCGv size)
18621862
gen_set_label(finish);
18631863
}
18641864

1865+
#if !defined(CONFIG_USER_ONLY)
1866+
enum hex_virt_opc {
1867+
HEX_VIRT_VMVERSION = 0x00,
1868+
HEX_VIRT_VMRETURN = 0x01,
1869+
HEX_VIRT_VMSETVEC = 0x02,
1870+
HEX_VIRT_VMSETIE = 0x03,
1871+
HEX_VIRT_VMGETIE = 0x04,
1872+
HEX_VIRT_VMINTOP = 0x05,
1873+
HEX_VIRT_VMCLRMAP = 0x0A,
1874+
HEX_VIRT_VMNEWMAP = 0x0B,
1875+
HEX_VIRT_VMCACHECTL = 0x0D,
1876+
HEX_VIRT_VMGETTIME = 0x0E,
1877+
HEX_VIRT_VMSETTIME = 0x0F,
1878+
HEX_VIRT_VMWAIT = 0x10,
1879+
HEX_VIRT_VMYIELD = 0x11,
1880+
HEX_VIRT_VMSTART = 0x12,
1881+
HEX_VIRT_VMSTOP = 0x13,
1882+
HEX_VIRT_VMVMPID = 0x14,
1883+
HEX_VIRT_VMSETREGS = 0x15,
1884+
HEX_VIRT_VMGETREGS = 0x16,
1885+
HEX_VIRT_VMTIMEROP = 0x18,
1886+
HEX_VIRT_VMPMUCTRL = 0x19,
1887+
HEX_VIRT_VMGETINFO = 0x1A,
1888+
};
1889+
1890+
#include "hex_vm.c.inc"
1891+
1892+
static void gen_vminst(DisasContext *ctx, int operand)
1893+
{
1894+
if (!ctx->has_hexagon_vm) {
1895+
/* FIXME: raise an exception instead? */
1896+
return;
1897+
}
1898+
1899+
/* TODO: when swapping guest/user, must exchange GOSP, R29... */
1900+
switch (operand) {
1901+
case HEX_VIRT_VMVERSION:
1902+
gen_vmversion();
1903+
break;
1904+
case HEX_VIRT_VMSETREGS:
1905+
gen_vmsetregs();
1906+
break;
1907+
case HEX_VIRT_VMGETREGS:
1908+
gen_vmgetregs();
1909+
break;
1910+
case HEX_VIRT_VMSETIE:
1911+
gen_vmsetie();
1912+
break;
1913+
case HEX_VIRT_VMGETIE:
1914+
gen_vmgetie();
1915+
break;
1916+
case HEX_VIRT_VMVMPID:
1917+
gen_vmvpid();
1918+
break;
1919+
case HEX_VIRT_VMCACHECTL:
1920+
gen_vmcache();
1921+
break;
1922+
case HEX_VIRT_VMSTOP:
1923+
gen_vmstop();
1924+
break;
1925+
case HEX_VIRT_VMYIELD:
1926+
gen_vmyield();
1927+
break;
1928+
case HEX_VIRT_VMGETTIME:
1929+
gen_vmgettime();
1930+
break;
1931+
case HEX_VIRT_VMRETURN:
1932+
gen_vmrte();
1933+
break;
1934+
case HEX_VIRT_VMCLRMAP:
1935+
gen_vmclrmap();
1936+
break;
1937+
case HEX_VIRT_VMNEWMAP:
1938+
gen_vmnewmap();
1939+
break;
1940+
case HEX_VIRT_VMSETVEC:
1941+
gen_vmsetvec();
1942+
break;
1943+
case HEX_VIRT_VMINTOP:
1944+
gen_vmintop();
1945+
break;
1946+
case HEX_VIRT_VMGETINFO:
1947+
gen_vmgetinfo();
1948+
break;
1949+
case HEX_VIRT_VMTIMEROP:
1950+
gen_vmtimerop();
1951+
break;
1952+
1953+
1954+
default:
1955+
/* FIXME: Invalid packet exception? */
1956+
fprintf(stderr, "Unknown VM instruction 0x%08x\n", operand);
1957+
g_assert_not_reached();
1958+
break;
1959+
}
1960+
}
1961+
#endif
1962+
18651963
#include "tcg_funcs_generated.c.inc"
18661964
#include "tcg_func_table_generated.c.inc"

target/hexagon/helper.h

+1
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ DEF_HELPER_2(greg_read, i32, env, i32)
148148
DEF_HELPER_2(greg_read_pair, i64, env, i32)
149149
DEF_HELPER_1(inc_gcycle_xt, void, env)
150150
DEF_HELPER_3(modify_ssr, void, env, i32, i32)
151+
DEF_HELPER_2(modify_syscfg, void, env, i32)
151152
DEF_HELPER_1(pending_interrupt, void, env)
152153
DEF_HELPER_3(raise_stack_overflow, void, env, i32, i32)
153154
DEF_HELPER_1(resched, void, env)

0 commit comments

Comments
 (0)