Skip to content

Commit 4eca11d

Browse files
committed
GIPC: Introduce G-stage table In Process Context (GIPC)
The current G-stage page table resides within the device context and is only bound to one DC (Device Context). Consequently, this feature limits the DC to serve only a single virtual machine, which means G-stage table In Device Context (GIDC). The GIPC capability [1] adds iohgatp in PC (Process Context), and makes RISC-V IOMMU support GIPC and GIDC simultaneously. This improves the virtualization scalability of heterogeneous programming in shared work queue scenarios [2]. Because RVI hasn't ratified GIPC, this patch uses custom bit fields of dc.tc & capability regs. [1] riscv-non-isa/riscv-iommu#413 [2] https://www.youtube.com/watch?v=-fuqzYedOb0 Signed-off-by: Guo Ren (Alibaba DAMO Academy) <[email protected]>
1 parent 18ad30a commit 4eca11d

File tree

6 files changed

+4511
-18
lines changed

6 files changed

+4511
-18
lines changed

packages/rv_iommu/rv_iommu_pkg.sv

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ package rv_iommu;
108108
// Translation Control
109109
typedef struct packed {
110110
logic [31:0] reserved_2;
111-
logic [7:0] custom;
111+
logic [6:0] custom;
112+
logic gipc;
112113
logic [11:0] reserved_1;
113114
logic sxl;
114115
logic sbe;
@@ -164,6 +165,7 @@ package rv_iommu;
164165
typedef struct packed {
165166
fsc_t fsc;
166167
pc_ta_t ta;
168+
iohgatp_t iohgatp;
167169
} pc_t;
168170

169171
//--------------------------
@@ -369,7 +371,8 @@ package rv_iommu;
369371

370372
// Capabilities (caps)
371373
typedef struct packed {
372-
logic [7:0] custom;
374+
logic [6:0] custom;
375+
logic gipc;
373376
logic [14:0] reserved_3;
374377
logic pd20;
375378
logic pd17;

packages/rv_iommu/rv_iommu_reg_pkg.sv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ package rv_iommu_reg_pkg;
100100
struct packed {
101101
logic q;
102102
} pd20;
103+
struct packed {
104+
logic q;
105+
} gipc;
103106
} iommu_reg2hw_capabilities_reg_t;
104107

105108
typedef struct packed {

rtl/software_interface/regmap/rv_iommu_regmap.sv

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ module rv_iommu_regmap #(
124124
logic capabilities_pd8_qs;
125125
logic capabilities_pd17_qs;
126126
logic capabilities_pd20_qs;
127+
logic capabilities_gipc_qs;
127128

128129
// fctl
129130
logic fctl_be_qs;
@@ -528,6 +529,9 @@ module rv_iommu_regmap #(
528529
assign reg2hw.capabilities.pd20.q = 1'h1;
529530
assign capabilities_pd20_qs = 1'h1;
530531

532+
// F[gipc]: 56:56
533+
assign reg2hw.capabilities.gipc.q = 1'h1;
534+
assign capabilities_gipc_qs = 1'h1;
531535

532536
// R[fctl]: V(False)
533537

@@ -3251,7 +3255,9 @@ module rv_iommu_regmap #(
32513255
reg_rdata_next[6] = capabilities_pd8_qs;
32523256
reg_rdata_next[7] = capabilities_pd17_qs;
32533257
reg_rdata_next[8] = capabilities_pd20_qs;
3254-
reg_rdata_next[31:9] = '0;
3258+
reg_rdata_next[23:9] = '0;
3259+
reg_rdata_next[24] = capabilities_gipc_qs;
3260+
reg_rdata_next[31:25] = '0;
32553261
end
32563262

32573263
// fctl

rtl/translation_logic/cdw/rv_iommu_cdw_pc.sv

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ module rv_iommu_cdw_pc #(
5252
input logic caps_msi_flat_i,
5353
input logic caps_amo_hwad_i,
5454
input logic caps_end_i, fctl_be_i,
55+
input logic caps_gipc_i,
5556

5657
// PC checks
5758
input logic dc_sxl_i,
@@ -85,6 +86,7 @@ module rv_iommu_cdw_pc #(
8586

8687
// from DC (for PC walks)
8788
input logic en_stage2_i, // Second-stage translation is enabled
89+
input logic gipc_i, // GIPC is enabled
8890
input logic [riscv::PPNW-1:0] pdtp_ppn_i, // PPN from DC.fsc.PPN
8991
input logic [3:0] pdtp_mode_i, // PDT levels from DC.fsc.MODE
9092

@@ -110,6 +112,7 @@ module rv_iommu_cdw_pc #(
110112

111113
rv_iommu::pc_ta_t pc_ta_q, pc_ta_n;
112114
rv_iommu::fsc_t pc_fsc_q, pc_fsc_n;
115+
rv_iommu::iohgatp_t pc_iohgatp_q, pc_iohgatp_n;
113116

114117
// DDTC / PDTC Update
115118
assign up_did_o = device_id_q;
@@ -118,6 +121,7 @@ module rv_iommu_cdw_pc #(
118121

119122
assign up_pc_content_o.ta = pc_ta_q;
120123
assign up_pc_content_o.fsc = pc_fsc_q;
124+
assign up_pc_content_o.iohgatp = pc_iohgatp_q;
121125

122126
// Cast read port to corresponding data structure
123127
rv_iommu::tc_t dc_tc;
@@ -127,6 +131,7 @@ module rv_iommu_cdw_pc #(
127131

128132
rv_iommu::pc_ta_t pc_ta;
129133
rv_iommu::fsc_t pc_fsc;
134+
rv_iommu::iohgatp_t pc_iohgatp;
130135

131136
rv_iommu::nl_entry_t nl;
132137

@@ -137,6 +142,7 @@ module rv_iommu_cdw_pc #(
137142

138143
assign pc_ta = rv_iommu::pc_ta_t'(mem_resp_i.r.data);
139144
assign pc_fsc = rv_iommu::fsc_t'(mem_resp_i.r.data);
145+
assign pc_iohgatp = rv_iommu::iohgatp_t'(mem_resp_i.r.data);
140146

141147
assign nl = rv_iommu::nl_entry_t'(mem_resp_i.r.data);
142148

@@ -192,13 +198,17 @@ module rv_iommu_cdw_pc #(
192198
// Signal MSI field config error to main FSM
193199
logic msi_check_error;
194200

201+
// Enable en_stage2
202+
logic en_stage2;
203+
assign en_stage2 = !gipc_i && en_stage2_i;
204+
195205
// PTW walking
196206
assign cdw_active_o = (state_q != IDLE);
197207
// Last CDW level
198208
assign is_last_cdw_lvl = (cdw_lvl_q == LVL1);
199209
// Determine whether we have loaded the entire DC/PC
200210
assign dc_fully_loaded = (MSITrans != rv_iommu::MSI_DISABLED) ? (entry_cnt_q == 3'b111) : (entry_cnt_q == 3'b100); // extended format w/out reserved DW (64-8 = 56 bytes)
201-
assign pc_fully_loaded = (entry_cnt_q == 3'b010); // always 16-bytes
211+
assign pc_fully_loaded = (gipc_i ? entry_cnt_q == 3'b011 : entry_cnt_q == 3'b010); // always 16-bytes, but (32-8 = 24) bytes for GIPC
202212
// PTW needs to know walk type to identify pdtp.PPN translations and select correct iohgatp source
203213
assign is_ddt_walk_o = is_ddt_walk_q;
204214

@@ -260,8 +270,8 @@ module rv_iommu_cdw_pc #(
260270
// AR
261271
mem_req_o.ar.id = 4'b0001;
262272
mem_req_o.ar.addr = {{riscv::XLEN-riscv::PLEN{1'b0}}, cdw_pptr_q}; // Physical address to access
263-
// Number of beats per burst (1 for non-leaf entries, 2 for PC, 7 for DC)
264-
mem_req_o.ar.len = (is_last_cdw_lvl) ? ((is_ddt_walk_q) ? (ar_len) : (8'd1)) : (8'd0);
273+
// Number of beats per burst (1 for non-leaf entries, 3/2 for PC, 7/4 for DC)
274+
mem_req_o.ar.len = (is_last_cdw_lvl) ? ((is_ddt_walk_q) ? (ar_len) : (gipc_i : (8'd2) : (8'd1))) : (8'd0);
265275
mem_req_o.ar.size = 3'b011; // 64 bits (8 bytes) per beat
266276
mem_req_o.ar.burst = axi_pkg::BURST_INCR; // Incremental start address
267277
mem_req_o.ar.lock = '0;
@@ -300,6 +310,7 @@ module rv_iommu_cdw_pc #(
300310
dc_fsc_n = dc_fsc_q;
301311
pc_ta_n = pc_ta_q;
302312
pc_fsc_n = pc_fsc_q;
313+
pc_iohgatp_n = pc_iohgatp_q;
303314

304315
case (state_q)
305316

@@ -347,13 +358,18 @@ module rv_iommu_cdw_pc #(
347358
// load pptr according to pdtp.MODE
348359
// PD20
349360
if (pdtp_mode_i == 4'b0011)
350-
cdw_pptr_n = {pdtp_ppn_i, 6'b0, req_pid_i[19:17], 3'b0}; // ... aaaa 0000 00bb b000
361+
cdw_pptr_n = {pdtp_ppn_i,
362+
gipc_i ? 5'b0 : 6'b0,
363+
gipc_i ? req_pid_i[19:16] : req_pid_i[19:17], 3'b0};
351364
// PD17
352365
else if (pdtp_mode_i == 4'b0010)
353-
cdw_pptr_n = {pdtp_ppn_i, req_pid_i[16:8], 3'b0}; // ... aaaa bbbb bbbb b000
366+
cdw_pptr_n = {pdtp_ppn_i,
367+
gipc_i ? req_pid_i[15:7] : req_pid_i[16:8], 3'b0};
354368
// PD8
355369
else if (pdtp_mode_i == 4'b0001)
356-
cdw_pptr_n = {pdtp_ppn_i, req_pid_i[7:0], 4'b0}; // ... aaaa bbbb bbbb 0000
370+
cdw_pptr_n = {pdtp_ppn_i,
371+
gipc_i ? req_pid_i[6:0] : req_pid_i[7:0],
372+
gipc_i ? 5'b0 : 4'b0};
357373
end
358374
end
359375

@@ -372,7 +388,7 @@ module rv_iommu_cdw_pc #(
372388
- Is Stage-2 enabled?
373389
- Is the last level of the DDT/PDT?
374390
*/
375-
case ({en_stage2_i, is_ddt_walk_q, is_last_cdw_lvl})
391+
case ({en_stage2, is_ddt_walk_q, is_last_cdw_lvl})
376392
// rdata will hold the PPN of a non-leaf PDT/DDT entry
377393
// Stage-2 is don't care for DC walks since iohgatp always provides a PPN
378394
3'b000, 3'b010, 3'b110: begin
@@ -431,7 +447,7 @@ module rv_iommu_cdw_pc #(
431447
(MSITrans == rv_iommu::MSI_DISABLED) ? (device_id_q[15:7]) : (device_id_q[14:6]),
432448
3'b0};
433449
else begin
434-
if (!en_stage2_i) cdw_pptr_n = {nl.ppn, process_id_q[16:8], 3'b0};
450+
if (!en_stage2) cdw_pptr_n = {nl.ppn, gipc_i ? process_id_q[15:7] : process_id_q[16:8], 3'b0};
435451
else cdw_pptr_n = {pdt_ppn_i, process_id_q[16:8], 3'b0};
436452
end
437453
end
@@ -441,7 +457,7 @@ module rv_iommu_cdw_pc #(
441457
if (is_ddt_walk_q) cdw_pptr_n = {nl.ppn,
442458
(MSITrans == rv_iommu::MSI_DISABLED) ? ({device_id_q[6:0], 5'b0}) : ({device_id_q[5:0], 6'b0})};
443459
else begin
444-
if (!en_stage2_i) cdw_pptr_n = {nl.ppn, process_id_q[7:0], 4'b0};
460+
if (!en_stage2) cdw_pptr_n = {nl.ppn, gipc_i ? process_id_q[6:0] : process_id_q[7:0], gipc_i ? 5'b0 : 4'b0};
445461
else cdw_pptr_n = {pdt_ppn_i, process_id_q[7:0], 4'b0};
446462
end
447463
end
@@ -470,7 +486,7 @@ module rv_iommu_cdw_pc #(
470486
end
471487

472488
// Last DW (When stage-2 is enabled we must verify if the DC has been updated with the translated pdtp.PPN)
473-
if ((is_ddt_walk_q && dc_fully_loaded && (ptw_done_q || !en_stage2_i || !dc_tc_q.pdtv)) ||
489+
if ((is_ddt_walk_q && dc_fully_loaded && (ptw_done_q || !en_stage2 || !dc_tc_q.pdtv)) ||
474490
(!is_ddt_walk_q && pc_fully_loaded)) begin
475491

476492
state_n = IDLE;
@@ -522,6 +538,26 @@ module rv_iommu_cdw_pc #(
522538
(dc_sxl_i && (!caps_sv32_i && pc_fsc.mode == 4'd8))) begin
523539
state_n = ERROR;
524540
cause_n = rv_iommu::PDT_ENTRY_MISCONFIGURED;
541+
if (gipc_i) begin
542+
wait_rlast_n = 1'b1;
543+
end
544+
end
545+
end
546+
547+
//PC.iohgatp
548+
4'b0010: begin
549+
pc_iohgatp_n = pc_iohgatp;
550+
551+
// Config checks
552+
if (!caps_gipc_i ||
553+
(!(pc_iohgatp.mode inside {4'd0, 4'd8, 4'd9, 4'd10})) ||
554+
(!fctl_gxl_i && ((!caps_sv39x4_i && pc_iohgatp.mode == 4'd8) ||
555+
(!caps_sv48x4_i && pc_iohgatp.mode == 4'd9) ||
556+
(!caps_sv57x4_i && pc_iohgatp.mode == 4'd10))) ||
557+
(fctl_gxl_i && (!caps_sv32x4_i && pc_iohgatp.mode == 4'd8)) ||
558+
(|pc_iohgatp.mode && |pc_iohgatp.ppn[1:0])) begin
559+
state_n = ERROR;
560+
cause_n = rv_iommu::PDT_ENTRY_MISCONFIGURED;
525561
end
526562
end
527563

@@ -612,7 +648,7 @@ module rv_iommu_cdw_pc #(
612648
else if (MSITrans == rv_iommu::MSI_DISABLED) begin
613649
// only if DC have an associated PC and Stage-2 is enabled, pdtp.PPN must be translated before being stored
614650
// otherwise, fsc.PPN holds iosatp field, which must be saved as a GPA
615-
if (en_stage2_i && dc_tc_q.pdtv)
651+
if (en_stage2 && dc_tc_q.pdtv)
616652
state_n = GUEST_TR;
617653
end
618654
end
@@ -806,7 +842,7 @@ module rv_iommu_cdw_pc #(
806842

807843
// only if DC have an associated PC and Stage-2 is enabled, pdtp.PPN must be translated before being stored
808844
// otherwise, fsc.PPN holds iosatp field, which must be saved as a GPA
809-
if (en_stage2_i && dc_tc_q.pdtv)
845+
if (en_stage2 && dc_tc_q.pdtv)
810846
translate_pdtp = 1'b1;
811847

812848
// Config checks
@@ -871,6 +907,7 @@ module rv_iommu_cdw_pc #(
871907
dc_fsc_q <= '0;
872908
pc_ta_q <= '0;
873909
pc_fsc_q <= '0;
910+
pc_iohgatp_q <= '0;
874911
ptw_done_q <= 1'b0;
875912
wait_rlast_q <= 1'b0;
876913
edge_trigger_q <= 1'b0;
@@ -890,6 +927,7 @@ module rv_iommu_cdw_pc #(
890927
dc_fsc_q <= dc_fsc_n;
891928
pc_ta_q <= pc_ta_n;
892929
pc_fsc_q <= pc_fsc_n;
930+
pc_iohgatp_q <= pc_iohgatp_n;
893931
ptw_done_q <= ptw_done_i;
894932
wait_rlast_q <= wait_rlast_n;
895933
edge_trigger_q <= edge_trigger_n;

rtl/translation_logic/wrapper/rv_iommu_tw_sv39x4_pc.sv

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,9 @@ module rv_iommu_tw_sv39x4_pc #(
220220
logic S1_en, S2_en;
221221
assign S1_en = ((dc_base.tc.pdtv && pdtc_lu_content.fsc.mode != 4'b0000) ||
222222
(!dc_base.tc.pdtv && dc_base.fsc.mode != 4'b0000) );
223-
assign S2_en = (dc_base.iohgatp.mode != 4'b0000);
223+
assign S2_en = (dc_base.iohgatp.mode != 4'b0000 ||
224+
(dc_base.tc.pdtv && dc_base.tc.gipc &&
225+
pdtc_lu_content.iohgatp.mode != 4'b0000));
224226

225227
// Alternative translation config for PTW implicit second-stage translations in CDW Walks
226228
logic ptw_en_1S, ptw_en_2S;
@@ -480,7 +482,7 @@ module rv_iommu_tw_sv39x4_pc #(
480482
.cause_code_o (ptw_cause_code ),
481483

482484
.en_1S_i (ptw_en_1S ), // Enable signal for stage 1 translation. Defined by DC/PC
483-
.en_2S_i (ptw_en_2S ), // Enable signal for stage 2 translation. Defined by DC only
485+
.en_2S_i (ptw_en_2S ), // Enable signal for stage 2 translation. Defined by DC/PC
484486
.is_store_i (is_store ), // Indicate whether this translation was triggered by a store or a load
485487
.is_rx_i (is_rx ), // Read-for-execute
486488

@@ -771,6 +773,7 @@ module rv_iommu_tw_sv39x4_pc #(
771773
.caps_msi_flat_i (capabilities_i.msi_flat.q ),
772774
.caps_amo_hwad_i (capabilities_i.amo_hwad.q ),
773775
.caps_end_i (capabilities_i.endi.q ),
776+
.caps_gipc_i (capabilities_i.gipc.q ),
774777
.fctl_be_i (fctl_i.be.q ),
775778

776779
// PC checks
@@ -805,6 +808,7 @@ module rv_iommu_tw_sv39x4_pc #(
805808

806809
// from DC (for PC walks)
807810
.en_stage2_i (S2_en ), // Second-stage translation is enabled
811+
.gipc_i (dc_base.tc.gipc ), // GIPC is enabled
808812
.pdtp_ppn_i (dc_base.fsc.ppn ), // PPN from DC.fsc.PPN
809813
.pdtp_mode_i (dc_base.fsc.mode ), // PDT levels from DC.fsc.MODE
810814

@@ -951,7 +955,7 @@ module rv_iommu_tw_sv39x4_pc #(
951955
else begin
952956
gscid = dc_base.iohgatp.gscid;
953957
pscid = pdtc_lu_content.ta.pscid;
954-
iohgatp_ppn = dc_base.iohgatp.ppn;
958+
iohgatp_ppn = dc_base.tc.gipc ? pdtc_lu_content.iohgatp.ppn : dc_base.iohgatp.ppn;
955959
iosatp_ppn = pdtc_lu_content.fsc.ppn;
956960
iotlb_access = 1'b1;
957961
end

0 commit comments

Comments
 (0)