Skip to content

Commit d83a7e3

Browse files
committed
draft: Implement vmnewmap inst
FIXME: while following the spec for vmnewmap and the kernel source, I thought I understood the expected behavior but based on what I've seen so far I think it's not yet implemented correctly. Signed-off-by: Brian Cain <[email protected]>
1 parent 704cd90 commit d83a7e3

File tree

5 files changed

+163
-14
lines changed

5 files changed

+163
-14
lines changed

docs/system/hexagon/hvm.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ Virtual Instructions
117117
* - vmnewmap
118118
- set new virtual memory map
119119
- 0xb
120-
- r0 contains logical address of new segment table, r1 =Type of translations
120+
- r0 contains logical address of new segment table, r1 = type of translations: 0 indicates a logical address of a zero-terminated linear list, 1 indicates a set of page tables.
121121
- r0 contains 0 on success, otherwise negative error code
122122
* - vmcache
123123
- VM cache control: not modeled

target/hexagon/helper.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ DEF_HELPER_2(nmi, void, env, i32)
5151
DEF_HELPER_3(setprio, void, env, i32, i32)
5252
DEF_HELPER_2(start, void, env, i32)
5353
DEF_HELPER_1(stop, void, env)
54+
55+
DEF_HELPER_4(vmnewmap, void, env, i32, i32, i32)
5456
#endif
5557

5658
DEF_HELPER_5(check_vtcm_memcpy, void, env, i32, i32, i32, i32)

target/hexagon/hex_vm.c.inc

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ static inline void gen_vmsetie(void)
4343

4444
TCGv new_syscfg = tcg_temp_new();
4545
tcg_gen_deposit_tl(new_syscfg, hex_g_sreg[HEX_SREG_SYSCFG],
46-
hex_gpr[HEX_REG_R00],
47-
reg_field_info[SYSCFG_GIE].offset,
46+
hex_gpr[HEX_REG_R00], reg_field_info[SYSCFG_GIE].offset,
4847
reg_field_info[SYSCFG_GIE].width);
4948
gen_helper_modify_syscfg(tcg_env, new_syscfg);
5049
tcg_gen_mov_tl(hex_gpr[HEX_REG_R00], old_ie);
@@ -96,7 +95,8 @@ static inline void gen_vmyield(void)
9695
}
9796
static inline void gen_vmnewmap(void)
9897
{
99-
/* g_assert_not_reached(); HACK FIXME */
98+
gen_helper_vmnewmap(tcg_env, hex_gpr[HEX_REG_R01], hex_gpr[HEX_REG_R00],
99+
hex_gpr[HEX_REG_R02]);
100100
}
101101
static inline void gen_vmclrmap(void)
102102
{
@@ -142,18 +142,14 @@ static inline void gen_vmintop(void)
142142
local_en);
143143
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_LOCDIS,
144144
local_dis);
145-
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_GET,
146-
get);
145+
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_GET, get);
147146
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_AFFINITY,
148147
affinity);
149-
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_PEEK,
150-
peek);
148+
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_PEEK, peek);
151149
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_STATUS,
152150
status);
153-
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_POST,
154-
post);
155-
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_CLEAR,
156-
clear);
151+
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_POST, post);
152+
tcg_gen_brcondi_tl(TCG_COND_EQ, hex_gpr[HEX_REG_R00], VMINTOP_CLEAR, clear);
157153

158154
TCGv irq_mask = tcg_temp_new();
159155
TCGv set_mask = tcg_temp_new();
@@ -286,8 +282,7 @@ static inline void gen_vmrte(void)
286282
reg_field_info[GSR_IE].offset,
287283
reg_field_info[GSR_IE].width);
288284
tcg_gen_deposit_tl(hex_g_sreg[HEX_SREG_SYSCFG], hex_g_sreg[HEX_SREG_SYSCFG],
289-
gsr_ie,
290-
reg_field_info[SYSCFG_GIE].offset,
285+
gsr_ie, reg_field_info[SYSCFG_GIE].offset,
291286
reg_field_info[SYSCFG_GIE].width);
292287

293288
TCGv gsr_um = tcg_temp_new();

target/hexagon/op_helper.c

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,6 +2708,147 @@ void HELPER(check_vtcm_memcpy)(CPUHexagonState *env, uint32_t dst, uint32_t src,
27082708
}
27092709
}
27102710

2711+
2712+
typedef enum {
2713+
HEXVM_ENTRY_DIRECTORY,
2714+
HEXVM_ENTRY_TABLE,
2715+
HEXVM_ENTRY_INVALID,
2716+
} HexVMPTEEntryType;
2717+
2718+
typedef struct {
2719+
HexVMPTEEntryType entry_type;
2720+
uint32_t page_size_bytes;
2721+
uint32_t l2_entries;
2722+
uint32_t addr_start_bit;
2723+
uint32_t addr_bit_count;
2724+
} l1_pte_types;
2725+
2726+
2727+
#define COPY_FIELD(dest, src, FIELD) \
2728+
dest = deposit64(dest, reg_field_info[FIELD].offset, \
2729+
reg_field_info[FIELD].width, \
2730+
extract32(src, reg_field_info[VM##FIELD].offset, \
2731+
reg_field_info[VM##FIELD].width))
2732+
2733+
void HELPER(vmnewmap)(CPUHexagonState *env, uint32_t map_type, uint32_t input,
2734+
uint32_t tlb_inval)
2735+
{
2736+
CPUState *cs = env_cpu(env);
2737+
static const l1_pte_types PTE_TYPES[] = {
2738+
/* FIXME: off-by-one bit start/count? */
2739+
{ HEXVM_ENTRY_DIRECTORY, 4 * 1024, 1024, 12, 20, },
2740+
{ HEXVM_ENTRY_DIRECTORY, 16 * 1024, 256, 10, 22, },
2741+
{ HEXVM_ENTRY_DIRECTORY, 64 * 1024, 64, 8, 24, },
2742+
{ HEXVM_ENTRY_DIRECTORY, 256 * 1024, 16, 6, 26, },
2743+
{ HEXVM_ENTRY_DIRECTORY, 1024 * 1024, 4, 4, 28, },
2744+
{ HEXVM_ENTRY_TABLE, 4 * 1024 * 1024, 0, 0, 0, },
2745+
{ HEXVM_ENTRY_TABLE, 16 * 1024 * 1024, 0, 0, 0, },
2746+
{ HEXVM_ENTRY_INVALID, 0, 0, 0, 0, },
2747+
};
2748+
static const int TYPE_MASK = 0x07;
2749+
2750+
bool fail = false;
2751+
2752+
/*
2753+
* LARGE PARTS OF THE CODE BELOW APPEARS TO BE WRONG. IT DOES
2754+
* NOT WORK AS EXPECTED.
2755+
*/
2756+
2757+
switch (map_type) {
2758+
case 0:
2759+
/* FIXME: linear list... */
2760+
g_assert_not_reached();
2761+
break;
2762+
case 1:
2763+
;
2764+
const l1_pte_types e = PTE_TYPES[input & TYPE_MASK];
2765+
switch (e.entry_type) {
2766+
case HEXVM_ENTRY_DIRECTORY:
2767+
;
2768+
uint32_t l2_table_la = input & ~(0x0f);
2769+
/* FIXME check the table addr alignment, should match table size */
2770+
uint32_t i;
2771+
for (i = 0; i < e.l2_entries; i++) {
2772+
/* L2 entries are 32-bits long */
2773+
uint32_t entry;
2774+
uint32_t offset = i * sizeof(entry);
2775+
address_space_read(cs->as, l2_table_la + offset,
2776+
MEMTXATTRS_UNSPECIFIED, &entry,
2777+
sizeof(entry));
2778+
2779+
/*
2780+
* How to know what terminates the list?
2781+
* linear lists are null-terminated.
2782+
*/
2783+
if (entry == 0) {
2784+
break;
2785+
}
2786+
uint64_t phys_entry = 0;
2787+
deposit64(phys_entry, reg_field_info[PTE_V].offset,
2788+
reg_field_info[PTE_V].width, true);
2789+
2790+
COPY_FIELD(phys_entry, entry, PTE_R);
2791+
COPY_FIELD(phys_entry, entry, PTE_W);
2792+
COPY_FIELD(phys_entry, entry, PTE_X);
2793+
COPY_FIELD(phys_entry, entry, PTE_U);
2794+
COPY_FIELD(phys_entry, entry, PTE_C);
2795+
uint32_t logical_page_num =
2796+
extract32(entry, e.addr_start_bit, e.addr_bit_count);
2797+
/* COPY_FIELD(phys_entry, entry, PTE_VPN); */
2798+
phys_entry =
2799+
deposit64(phys_entry, reg_field_info[PTE_PPD].offset,
2800+
reg_field_info[PTE_PPD].width, logical_page_num);
2801+
phys_entry =
2802+
deposit64(phys_entry, reg_field_info[PTE_VPN].offset,
2803+
reg_field_info[PTE_VPN].width, logical_page_num);
2804+
2805+
bool r = extract32(entry, reg_field_info[VMPTE_R].offset,
2806+
reg_field_info[VMPTE_R].width);
2807+
bool w = extract32(entry, reg_field_info[VMPTE_W].offset,
2808+
reg_field_info[VMPTE_W].width);
2809+
bool x = extract32(entry, reg_field_info[VMPTE_X].offset,
2810+
reg_field_info[VMPTE_X].width);
2811+
g_assert(r || w || x);
2812+
2813+
switch (e.page_size_bytes) {
2814+
case 4 * 1024:
2815+
phys_entry = deposit64(phys_entry, 0, 1, true);
2816+
break;
2817+
case 16 * 1024:
2818+
phys_entry = deposit64(
2819+
phys_entry, reg_field_info[PTE_PPD].offset, 1, true);
2820+
break;
2821+
default:
2822+
g_assert_not_reached();
2823+
break;
2824+
}
2825+
2826+
/*
2827+
* How to know which base TLB index to use?
2828+
* Keep some state for where the last added one was?
2829+
*/
2830+
hex_tlbw(env, i, phys_entry);
2831+
}
2832+
g_assert_not_reached();
2833+
2834+
break;
2835+
case HEXVM_ENTRY_TABLE:
2836+
g_assert_not_reached();
2837+
break;
2838+
case HEXVM_ENTRY_INVALID:
2839+
default:
2840+
/* FIXME raise protection violation exception event */
2841+
fail = true;
2842+
break;
2843+
}
2844+
break;
2845+
default:
2846+
fail = true;
2847+
break;
2848+
}
2849+
env->gpr[HEX_REG_R00] = fail ? -1 : 0;
2850+
}
2851+
27112852
/* These macros can be referenced in the generated helper functions */
27122853
#define warn(...) /* Nothing */
27132854
#define fatal(...) g_assert_not_reached();

target/hexagon/reg_fields_def.h.inc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,14 @@ DEF_REG_FIELD(PMUCFG_THMASK, 16, 3)
211211
DEF_REG_FIELD(GSR_UM, 31, 1)
212212
DEF_REG_FIELD(GSR_IE, 30, 1)
213213
DEF_REG_FIELD(GSR_CAUSE, 0, 16)
214+
215+
/* Hexagon VM L2 Page table entries */
216+
217+
/* VPN aka LPN: */
218+
DEF_REG_FIELD(VMPTE_VPN, 12, 20)
219+
DEF_REG_FIELD(VMPTE_X, 11, 1)
220+
DEF_REG_FIELD(VMPTE_W, 10, 1)
221+
DEF_REG_FIELD(VMPTE_R, 9, 1)
222+
DEF_REG_FIELD(VMPTE_C, 6, 3)
223+
DEF_REG_FIELD(VMPTE_U, 5, 1)
224+
DEF_REG_FIELD(VMPTE_TRUSTED, 4, 1)

0 commit comments

Comments
 (0)