@@ -2708,6 +2708,147 @@ void HELPER(check_vtcm_memcpy)(CPUHexagonState *env, uint32_t dst, uint32_t src,
2708
2708
}
2709
2709
}
2710
2710
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
+
2711
2852
/* These macros can be referenced in the generated helper functions */
2712
2853
#define warn (...) /* Nothing */
2713
2854
#define fatal (...) g_assert_not_reached();
0 commit comments