aboutsummaryrefslogtreecommitdiffstats
path: root/techlibs
diff options
context:
space:
mode:
Diffstat (limited to 'techlibs')
-rw-r--r--techlibs/ecp5/.gitignore9
-rw-r--r--techlibs/ecp5/Makefile.inc34
-rw-r--r--techlibs/ecp5/bram.txt29
-rwxr-xr-xtechlibs/ecp5/brams_connect.py46
-rwxr-xr-xtechlibs/ecp5/brams_init.py22
-rw-r--r--techlibs/ecp5/brams_map.v115
-rw-r--r--techlibs/ecp5/cells_map.v32
-rw-r--r--techlibs/ecp5/cells_sim.v99
-rw-r--r--techlibs/ecp5/synth_ecp5.cc5
-rw-r--r--techlibs/xilinx/synth_xilinx.cc5
10 files changed, 373 insertions, 23 deletions
diff --git a/techlibs/ecp5/.gitignore b/techlibs/ecp5/.gitignore
new file mode 100644
index 000000000..54c329735
--- /dev/null
+++ b/techlibs/ecp5/.gitignore
@@ -0,0 +1,9 @@
+bram_init_1_2_4.vh
+bram_init_9_18_36.vh
+brams_init.mk
+bram_conn_1.vh
+bram_conn_2.vh
+bram_conn_4.vh
+bram_conn_9.vh
+bram_conn_18.vh
+brams_connect.mk
diff --git a/techlibs/ecp5/Makefile.inc b/techlibs/ecp5/Makefile.inc
index 9d3247347..f45859392 100644
--- a/techlibs/ecp5/Makefile.inc
+++ b/techlibs/ecp5/Makefile.inc
@@ -5,4 +5,38 @@ $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/drams_map.v))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dram.txt))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams_map.v))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt))
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
+
+EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
+.SECONDARY: techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
+
+techlibs/ecp5/brams_init.mk: techlibs/ecp5/brams_init.py
+ $(Q) mkdir -p techlibs/ecp5
+ $(P) python3 $<
+ $(Q) touch $@
+
+techlibs/ecp5/brams_connect.mk: techlibs/ecp5/brams_connect.py
+ $(Q) mkdir -p techlibs/ecp5
+ $(P) python3 $<
+ $(Q) touch $@
+
+
+techlibs/ecp5/bram_init_1_2_4.vh: techlibs/ecp5/brams_init.mk
+techlibs/ecp5/bram_init_9_18_36.vh: techlibs/ecp5/brams_init.mk
+
+techlibs/ecp5/bram_conn_1.vh: techlibs/ecp5/brams_connect.mk
+techlibs/ecp5/bram_conn_2.vh: techlibs/ecp5/brams_connect.mk
+techlibs/ecp5/bram_conn_4.vh: techlibs/ecp5/brams_connect.mk
+techlibs/ecp5/bram_conn_9.vh: techlibs/ecp5/brams_connect.mk
+techlibs/ecp5/bram_conn_18.vh: techlibs/ecp5/brams_connect.mk
+
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_init_1_2_4.vh))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_init_9_18_36.vh))
+
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_1.vh))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_2.vh))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_4.vh))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_9.vh))
+$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram_conn_18.vh))
diff --git a/techlibs/ecp5/bram.txt b/techlibs/ecp5/bram.txt
new file mode 100644
index 000000000..f223a42b8
--- /dev/null
+++ b/techlibs/ecp5/bram.txt
@@ -0,0 +1,29 @@
+bram $__ECP5_DP16KD
+ init 1
+
+ abits 10 @a10d18
+ dbits 18 @a10d18
+ abits 11 @a11d9
+ dbits 9 @a11d9
+ abits 12 @a12d4
+ dbits 4 @a12d4
+ abits 13 @a13d2
+ dbits 2 @a13d2
+ abits 14 @a14d1
+ dbits 1 @a14d1
+
+ groups 2
+ ports 1 1
+ wrmode 1 0
+ enable 2 1 @a10d18
+ enable 1 1 @a11d9 @a12d4 @a13d2 @a14d1
+ transp 0 2
+ clocks 2 3
+ clkpol 2 3
+endbram
+
+match $__ECP5_DP16KD
+ min bits 2048
+ min efficiency 5
+ shuffle_enable B
+endmatch
diff --git a/techlibs/ecp5/brams_connect.py b/techlibs/ecp5/brams_connect.py
new file mode 100755
index 000000000..f86dcfcf0
--- /dev/null
+++ b/techlibs/ecp5/brams_connect.py
@@ -0,0 +1,46 @@
+#!/usr/bin/env python3
+
+def write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits):
+ ada_conn = [".ADA%d(%s)" % (i, ada_bits[i]) for i in range(len(ada_bits))]
+ adb_conn = [".ADB%d(%s)" % (i, adb_bits[i]) for i in range(len(adb_bits))]
+ dia_conn = [".DIA%d(%s)" % (i, dia_bits[i]) for i in range(len(dia_bits))]
+ dob_conn = [".DOB%d(%s)" % (i, dob_bits[i]) for i in range(len(dob_bits))]
+ print(" %s," % ", ".join(ada_conn), file=f)
+ print(" %s," % ", ".join(adb_conn), file=f)
+ print(" %s," % ", ".join(dia_conn), file=f)
+ print(" %s," % ", ".join(dob_conn), file=f)
+
+with open("techlibs/ecp5/bram_conn_1.vh", "w") as f:
+ ada_bits = ["A1ADDR[%d]" % i for i in range(14)]
+ adb_bits = ["B1ADDR[%d]" % i for i in range(14)]
+ dia_bits = ["A1DATA[0]"] + ["1'b0" for i in range(17)]
+ dob_bits = ["B1DATA[0]"]
+ write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
+
+with open("techlibs/ecp5/bram_conn_2.vh", "w") as f:
+ ada_bits = ["1'b0"] + ["A1ADDR[%d]" % i for i in range(13)]
+ adb_bits = ["1'b0"] + ["B1ADDR[%d]" % i for i in range(13)]
+ dia_bits = ["A1DATA[%d]" % i for i in range(2)] + ["1'b0" for i in range(16)]
+ dob_bits = ["B1DATA[%d]" % i for i in range(2)]
+ write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
+
+with open("techlibs/ecp5/bram_conn_4.vh", "w") as f:
+ ada_bits = ["1'b0", "1'b0"] + ["A1ADDR[%d]" % i for i in range(12)]
+ adb_bits = ["1'b0", "1'b0"] + ["B1ADDR[%d]" % i for i in range(12)]
+ dia_bits = ["A1DATA[%d]" % i for i in range(4)] + ["1'b0" for i in range(14)]
+ dob_bits = ["B1DATA[%d]" % i for i in range(4)]
+ write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
+
+with open("techlibs/ecp5/bram_conn_9.vh", "w") as f:
+ ada_bits = ["1'b0", "1'b0", "1'b0"] + ["A1ADDR[%d]" % i for i in range(11)]
+ adb_bits = ["1'b0", "1'b0", "1'b0"] + ["B1ADDR[%d]" % i for i in range(11)]
+ dia_bits = ["A1DATA[%d]" % i for i in range(9)] + ["1'b0" for i in range(9)]
+ dob_bits = ["B1DATA[%d]" % i for i in range(9)]
+ write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
+
+with open("techlibs/ecp5/bram_conn_18.vh", "w") as f:
+ ada_bits = ["A1EN[0]", "A1EN[1]", "1'b0", "1'b0"] + ["A1ADDR[%d]" % i for i in range(10)]
+ adb_bits = ["1'b0", "1'b0", "1'b0", "1'b0"] + ["B1ADDR[%d]" % i for i in range(10)]
+ dia_bits = ["A1DATA[%d]" % i for i in range(18)]
+ dob_bits = ["B1DATA[%d]" % i for i in range(18)]
+ write_bus_ports(f, ada_bits, adb_bits, dia_bits, dob_bits)
diff --git a/techlibs/ecp5/brams_init.py b/techlibs/ecp5/brams_init.py
new file mode 100755
index 000000000..96a47bdcd
--- /dev/null
+++ b/techlibs/ecp5/brams_init.py
@@ -0,0 +1,22 @@
+#!/usr/bin/env python3
+with open("techlibs/ecp5/bram_init_1_2_4.vh", "w") as f:
+ for i in range(0, 0x40):
+ init_snippets = []
+ for j in range(32):
+ init_snippets.append("INIT[%4d*8 +: 8]" % (32 * i + j))
+ init_snippets.append("3'b000" if (j % 2 == 1) else "1'b0")
+ init_snippets = list(reversed(init_snippets))
+ for k in range(8, 64, 8):
+ init_snippets[k] = "\n " + init_snippets[k]
+ print(".INITVAL_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
+
+with open("techlibs/ecp5/bram_init_9_18_36.vh", "w") as f:
+ for i in range(0, 0x40):
+ init_snippets = []
+ for j in range(16):
+ init_snippets.append("INIT[%3d*18 +: 18]" % (16 * i + j))
+ init_snippets.append("2'b00")
+ init_snippets = list(reversed(init_snippets))
+ for k in range(8, 32, 8):
+ init_snippets[k] = "\n " + init_snippets[k]
+ print(".INITVAL_%02X({%s})," % (i, ", ".join(init_snippets)), file=f)
diff --git a/techlibs/ecp5/brams_map.v b/techlibs/ecp5/brams_map.v
new file mode 100644
index 000000000..b2c136863
--- /dev/null
+++ b/techlibs/ecp5/brams_map.v
@@ -0,0 +1,115 @@
+module \$__ECP5_DP16KD (CLK2, CLK3, A1ADDR, A1DATA, A1EN, B1ADDR, B1DATA, B1EN);
+ parameter CFG_ABITS = 10;
+ parameter CFG_DBITS = 18;
+ parameter CFG_ENABLE_A = 2;
+
+ parameter CLKPOL2 = 1;
+ parameter CLKPOL3 = 1;
+ parameter [18431:0] INIT = 18432'bx;
+ parameter TRANSP2 = 0;
+
+ input CLK2;
+ input CLK3;
+
+ input [CFG_ABITS-1:0] A1ADDR;
+ input [CFG_DBITS-1:0] A1DATA;
+ input [CFG_ENABLE_A-1:0] A1EN;
+
+ input [CFG_ABITS-1:0] B1ADDR;
+ output [CFG_DBITS-1:0] B1DATA;
+ input B1EN;
+
+ localparam CLKAMUX = CLKPOL2 ? "CLKA" : "INV";
+ localparam CLKBMUX = CLKPOL3 ? "CLKB" : "INV";
+
+ localparam WRITEMODE_A = TRANSP2 ? "WRITETHROUGH" : "READBEFOREWRITE";
+
+ generate if (CFG_DBITS == 1) begin
+ DP16KD #(
+ `include "bram_init_1_2_4.vh"
+ .DATA_WIDTH_A(1),
+ .DATA_WIDTH_B(1),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WRITEMODE_A(WRITEMODE_A),
+ .WRITEMODE_B("READBEFOREWRITE"),
+ .GSR("DISABLED")
+ ) _TECHMAP_REPLACE_ (
+ `include "bram_conn_1.vh"
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1),
+ .WEB(1'b0), .CEB(B1EN), .OCEB(1'b1),
+ .RSTA(1'b0), .RSTB(1'b0)
+ );
+ end else if (CFG_DBITS == 2) begin
+ DP16KD #(
+ `include "bram_init_1_2_4.vh"
+ .DATA_WIDTH_A(2),
+ .DATA_WIDTH_B(2),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WRITEMODE_A(WRITEMODE_A),
+ .WRITEMODE_B("READBEFOREWRITE"),
+ .GSR("DISABLED")
+ ) _TECHMAP_REPLACE_ (
+ `include "bram_conn_2.vh"
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1),
+ .WEB(1'b0), .CEB(B1EN), .OCEB(1'b1),
+ .RSTA(1'b0), .RSTB(1'b0)
+ );
+ end else if (CFG_DBITS <= 4) begin
+ DP16KD #(
+ `include "bram_init_1_2_4.vh"
+ .DATA_WIDTH_A(4),
+ .DATA_WIDTH_B(4),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WRITEMODE_A(WRITEMODE_A),
+ .WRITEMODE_B("READBEFOREWRITE"),
+ .GSR("DISABLED")
+ ) _TECHMAP_REPLACE_ (
+ `include "bram_conn_4.vh"
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1),
+ .WEB(1'b0), .CEB(B1EN), .OCEB(1'b1),
+ .RSTA(1'b0), .RSTB(1'b0)
+ );
+ end else if (CFG_DBITS <= 9) begin
+ DP16KD #(
+ `include "bram_init_9_18_36.vh"
+ .DATA_WIDTH_A(9),
+ .DATA_WIDTH_B(9),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WRITEMODE_A(WRITEMODE_A),
+ .WRITEMODE_B("READBEFOREWRITE"),
+ .GSR("DISABLED")
+ ) _TECHMAP_REPLACE_ (
+ `include "bram_conn_9.vh"
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1),
+ .WEB(1'b0), .CEB(B1EN), .OCEB(1'b1),
+ .RSTA(1'b0), .RSTB(1'b0)
+ );
+ end else if (CFG_DBITS <= 18) begin
+ DP16KD #(
+ `include "bram_init_9_18_36.vh"
+ .DATA_WIDTH_A(18),
+ .DATA_WIDTH_B(18),
+ .CLKAMUX(CLKAMUX),
+ .CLKBMUX(CLKBMUX),
+ .WRITEMODE_A(WRITEMODE_A),
+ .WRITEMODE_B("READBEFOREWRITE"),
+ .GSR("DISABLED")
+ ) _TECHMAP_REPLACE_ (
+ `include "bram_conn_18.vh"
+ .CLKA(CLK2), .CLKB(CLK3),
+ .WEA(|A1EN), .CEA(1'b1), .OCEA(1'b1),
+ .WEB(1'b0), .CEB(B1EN), .OCEB(1'b1),
+ .RSTA(1'b0), .RSTB(1'b0)
+ );
+ end else begin
+ wire TECHMAP_FAIL = 1'b1;
+ end endgenerate
+endmodule
diff --git a/techlibs/ecp5/cells_map.v b/techlibs/ecp5/cells_map.v
index 48162a4dc..23182bdeb 100644
--- a/techlibs/ecp5/cells_map.v
+++ b/techlibs/ecp5/cells_map.v
@@ -7,40 +7,40 @@ module \$_DFFE_PN_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .C
module \$_DFFE_NP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
module \$_DFFE_PP_ (input D, C, E, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(1'b0), .DI(D), .Q(Q)); endmodule
-module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$_DFF_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$_DFF_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$_DFF_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$_DFF_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$_DFF_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_NN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_NN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_PN0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$__DFFS_PN1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_NP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_NP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_PP0_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFS_PP1_ (input D, C, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("1"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$__DFFE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_PP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFE_PP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("ASYNC")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
-module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("INV"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_NN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_NN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_PN0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
+module \$__DFFSE_PN1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("CLK"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(!R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_NP0 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("RESET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
module \$__DFFSE_NP1 (input D, C, E, R, output Q); TRELLIS_FF #(.GSR("DISABLED"), .CEMUX("CE"), .CLKMUX("INV"), .LSRMUX("LSR"), .REGSET("SET"), .SRMODE("LSR_OVER_CE")) _TECHMAP_REPLACE_ (.CLK(C), .CE(E), .LSR(R), .DI(D), .Q(Q)); endmodule
diff --git a/techlibs/ecp5/cells_sim.v b/techlibs/ecp5/cells_sim.v
index 1700694e8..e43632c64 100644
--- a/techlibs/ecp5/cells_sim.v
+++ b/techlibs/ecp5/cells_sim.v
@@ -446,3 +446,102 @@ module TRELLIS_SLICE(
);
endmodule
+(* blackbox *)
+module DP16KD(
+ input DIA17, DIA16, DIA15, DIA14, DIA13, DIA12, DIA11, DIA10, DIA9, DIA8, DIA7, DIA6, DIA5, DIA4, DIA3, DIA2, DIA1, DIA0,
+ input ADA13, ADA12, ADA11, ADA10, ADA9, ADA8, ADA7, ADA6, ADA5, ADA4, ADA3, ADA2, ADA1, ADA0,
+ input CEA, OCEA, CLKA, WEA, RSTA,
+ input CSA2, CSA1, CSA0,
+ output DOA17, DOA16, DOA15, DOA14, DOA13, DOA12, DOA11, DOA10, DOA9, DOA8, DOA7, DOA6, DOA5, DOA4, DOA3, DOA2, DOA1, DOA0,
+
+ input DIB17, DIB16, DIB15, DIB14, DIB13, DIB12, DIB11, DIB10, DIB9, DIB8, DIB7, DIB6, DIB5, DIB4, DIB3, DIB2, DIB1, DIB0,
+ input ADB13, ADB12, ADB11, ADB10, ADB9, ADB8, ADB7, ADB6, ADB5, ADB4, ADB3, ADB2, ADB1, ADB0,
+ input CEB, OCEB, CLKB, WEB, RSTB,
+ input CSB2, CSB1, CSB0,
+ output DOB17, DOB16, DOB15, DOB14, DOB13, DOB12, DOB11, DOB10, DOB9, DOB8, DOB7, DOB6, DOB5, DOB4, DOB3, DOB2, DOB1, DOB0
+);
+ parameter DATA_WIDTH_A = 18;
+ parameter DATA_WIDTH_B = 18;
+
+ parameter REGMODE_A = "NOREG";
+ parameter REGMODE_B = "NOREG";
+
+ parameter RESETMODE = "SYNC";
+ parameter ASYNC_RESET_RELEASE = "SYNC";
+
+ parameter CSDECODE_A = "0b000";
+ parameter CSDECODE_B = "0b000";
+
+ parameter WRITEMODE_A = "NORMAL";
+ parameter WRITEMODE_B = "NORMAL";
+
+ parameter CLKAMUX = "CLKA";
+ parameter CLKBMUX = "CLKB";
+
+ parameter GSR = "ENABLED";
+
+ parameter INITVAL_00 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_01 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_02 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_03 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_04 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_05 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_06 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_07 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_08 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_09 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_0F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_10 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_11 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_12 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_13 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_14 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_15 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_16 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_17 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_18 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_19 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_1F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_20 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_21 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_22 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_23 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_24 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_25 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_26 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_27 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_28 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_29 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_2F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_30 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_31 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_32 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_33 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_34 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_35 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_36 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_37 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_38 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_39 = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3A = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3B = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3C = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3D = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3E = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+ parameter INITVAL_3F = 320'h00000000000000000000000000000000000000000000000000000000000000000000000000000000;
+endmodule
diff --git a/techlibs/ecp5/synth_ecp5.cc b/techlibs/ecp5/synth_ecp5.cc
index a13dd8d41..ab56a9444 100644
--- a/techlibs/ecp5/synth_ecp5.cc
+++ b/techlibs/ecp5/synth_ecp5.cc
@@ -222,11 +222,8 @@ struct SynthEcp5Pass : public ScriptPass
if (!nobram && check_label("bram", "(skip if -nobram)"))
{
- //TODO
-#if 0
- run("memory_bram -rules +/ecp5/brams.txt");
+ run("memory_bram -rules +/ecp5/bram.txt");
run("techmap -map +/ecp5/brams_map.v");
-#endif
}
if (!nodram && check_label("dram", "(skip if -nodram)"))
diff --git a/techlibs/xilinx/synth_xilinx.cc b/techlibs/xilinx/synth_xilinx.cc
index 590fe61d2..b27c08529 100644
--- a/techlibs/xilinx/synth_xilinx.cc
+++ b/techlibs/xilinx/synth_xilinx.cc
@@ -235,10 +235,9 @@ struct SynthXilinxPass : public Pass
if (check_label(active, run_from, run_to, "map_cells"))
{
+ Pass::call(design, "techmap -map +/xilinx/cells_map.v");
if (vpr)
- Pass::call(design, "techmap -D NO_LUT -map +/xilinx/cells_map.v");
- else
- Pass::call(design, "techmap -map +/xilinx/cells_map.v");
+ Pass::call(design, "techmap -map +/xilinx/lut2lut.v");
Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT");
Pass::call(design, "clean");
}
xc_ia64_copy_to_domain_pages(xc_interface *xch, uint32_t domid, void* src_page, unsigned long dst_pfn, int nr_pages) { // N.B. gva should be page aligned int i; for (i = 0; i < nr_pages; i++) { if (xc_copy_to_domain_page(xch, domid, dst_pfn + i, src_page + (i << PAGE_SHIFT))) return -1; } return 0; } #define HOB_SIGNATURE 0x3436474953424f48 // "HOBSIG64" #define GFW_HOB_START ((4UL<<30)-(14UL<<20)) // 4G - 14M #define GFW_HOB_SIZE (1UL<<20) // 1M typedef struct { unsigned long signature; unsigned int type; unsigned int length; } HOB_GENERIC_HEADER; /* * INFO HOB is the first data data in one HOB list * it contains the control information of the HOB list */ typedef struct { HOB_GENERIC_HEADER header; unsigned long length; // current length of hob unsigned long cur_pos; // current poisiton of hob unsigned long buf_size; // size of hob buffer } HOB_INFO; typedef struct{ unsigned long start; unsigned long size; } hob_mem_t; typedef enum { HOB_TYPE_INFO=0, HOB_TYPE_TERMINAL, HOB_TYPE_MEM, HOB_TYPE_PAL_BUS_GET_FEATURES_DATA, HOB_TYPE_PAL_CACHE_SUMMARY, HOB_TYPE_PAL_MEM_ATTRIB, HOB_TYPE_PAL_CACHE_INFO, HOB_TYPE_PAL_CACHE_PROT_INFO, HOB_TYPE_PAL_DEBUG_INFO, HOB_TYPE_PAL_FIXED_ADDR, HOB_TYPE_PAL_FREQ_BASE, HOB_TYPE_PAL_FREQ_RATIOS, HOB_TYPE_PAL_HALT_INFO, HOB_TYPE_PAL_PERF_MON_INFO, HOB_TYPE_PAL_PROC_GET_FEATURES, HOB_TYPE_PAL_PTCE_INFO, HOB_TYPE_PAL_REGISTER_INFO, HOB_TYPE_PAL_RSE_INFO, HOB_TYPE_PAL_TEST_INFO, HOB_TYPE_PAL_VM_SUMMARY, HOB_TYPE_PAL_VM_INFO, HOB_TYPE_PAL_VM_PAGE_SIZE, HOB_TYPE_NR_VCPU, HOB_TYPE_NVRAM, HOB_TYPE_MAX } hob_type_t; static int hob_init(void *buffer ,unsigned long buf_size); static int add_pal_hob(void* hob_buf); static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size); static int add_vcpus_hob(void* hob_buf, unsigned long nr_vcpu); static int add_nvram_hob(void* hob_buf, unsigned long nvram_addr); static int build_hob(xc_interface *xch, void* hob_buf, unsigned long hob_buf_size, unsigned long dom_mem_size, unsigned long vcpus, unsigned long nvram_addr); static int load_hob(xc_interface *xch,uint32_t dom, void *hob_buf); static int xc_ia64_build_hob(xc_interface *xch, uint32_t dom, unsigned long memsize, unsigned long vcpus, unsigned long nvram_addr) { char *hob_buf; hob_buf = malloc(GFW_HOB_SIZE); if (hob_buf == NULL) { PERROR("Could not allocate hob"); return -1; } if (build_hob(xch, hob_buf, GFW_HOB_SIZE, memsize, vcpus, nvram_addr) < 0) { free(hob_buf); PERROR("Could not build hob"); return -1; } if (load_hob(xch, dom, hob_buf) < 0) { free(hob_buf); PERROR("Could not load hob"); return -1; } free(hob_buf); return 0; } static int hob_init(void *buffer, unsigned long buf_size) { HOB_INFO *phit; HOB_GENERIC_HEADER *terminal; if (sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER) > buf_size) { // buffer too small return -1; } phit = (HOB_INFO*)buffer; phit->header.signature = HOB_SIGNATURE; phit->header.type = HOB_TYPE_INFO; phit->header.length = sizeof(HOB_INFO); phit->length = sizeof(HOB_INFO) + sizeof(HOB_GENERIC_HEADER); phit->cur_pos = 0; phit->buf_size = buf_size; terminal = (HOB_GENERIC_HEADER*)(buffer + sizeof(HOB_INFO)); terminal->signature = HOB_SIGNATURE; terminal->type = HOB_TYPE_TERMINAL; terminal->length = sizeof(HOB_GENERIC_HEADER); return 0; } /* * Add a new HOB to the HOB List. * * hob_start - start address of hob buffer * type - type of the hob to be added * data - data of the hob to be added * data_size - size of the data */ static int hob_add(void* hob_start, int type, void* data, int data_size) { HOB_INFO *phit; HOB_GENERIC_HEADER *newhob, *tail; phit = (HOB_INFO*)hob_start; if (phit->length + data_size > phit->buf_size) { // no space for new hob return -1; } //append new HOB newhob = (HOB_GENERIC_HEADER*)(hob_start + phit->length - sizeof(HOB_GENERIC_HEADER)); newhob->signature = HOB_SIGNATURE; newhob->type = type; newhob->length = data_size + sizeof(HOB_GENERIC_HEADER); memcpy((void*)newhob + sizeof(HOB_GENERIC_HEADER), data, data_size); // append terminal HOB tail = (HOB_GENERIC_HEADER*)(hob_start + phit->length + data_size); tail->signature = HOB_SIGNATURE; tail->type = HOB_TYPE_TERMINAL; tail->length = sizeof(HOB_GENERIC_HEADER); // adjust HOB list length phit->length += sizeof(HOB_GENERIC_HEADER) + data_size; return 0; } static int get_hob_size(xc_interface *xch, void* hob_buf) { HOB_INFO *phit = (HOB_INFO*)hob_buf; if (phit->header.signature != HOB_SIGNATURE) { PERROR("xc_get_hob_size:Incorrect signature"); return -1; } return phit->length; } static int build_hob(xc_interface *xch, void* hob_buf, unsigned long hob_buf_size, unsigned long dom_mem_size, unsigned long vcpus, unsigned long nvram_addr) { //Init HOB List if (hob_init(hob_buf, hob_buf_size) < 0) { PERROR("buffer too small"); goto err_out; } if (add_mem_hob(hob_buf,dom_mem_size) < 0) { PERROR("Add memory hob failed, buffer too small"); goto err_out; } if (add_vcpus_hob(hob_buf, vcpus) < 0) { PERROR("Add NR_VCPU hob failed, buffer too small"); goto err_out; } if (add_pal_hob( hob_buf ) < 0) { PERROR("Add PAL hob failed, buffer too small"); goto err_out; } if (add_nvram_hob( hob_buf, nvram_addr ) < 0) { PERROR("Add nvram hob failed, buffer too small"); goto err_out; } return 0; err_out: return -1; } static int load_hob(xc_interface *xch, uint32_t dom, void *hob_buf) { // hob_buf should be page aligned int hob_size; int nr_pages; hob_size = get_hob_size(xch, hob_buf); if (hob_size < 0) { PERROR("Invalid hob data"); return -1; } if (hob_size > GFW_HOB_SIZE) { PERROR("No enough memory for hob data"); return -1; } nr_pages = (hob_size + PAGE_SIZE -1) >> PAGE_SHIFT; return xc_ia64_copy_to_domain_pages(xch, dom, hob_buf, GFW_HOB_START >> PAGE_SHIFT, nr_pages); } #define MIN(x, y) (((x) < (y)) ? (x) : (y)) static int add_mem_hob(void* hob_buf, unsigned long dom_mem_size) { hob_mem_t memhob; // less than 3G accounting VGA RAM hole memhob.start = 0; if (dom_mem_size < VGA_IO_START) memhob.size = dom_mem_size; else memhob.size = MIN(dom_mem_size + VGA_IO_SIZE, 0xC0000000); if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0) return -1; if (dom_mem_size > 0xC0000000) { // 4G ~ 4G+remain memhob.start = 0x100000000; //4G memhob.size = dom_mem_size + VGA_IO_SIZE - 0xC0000000; if (hob_add(hob_buf, HOB_TYPE_MEM, &memhob, sizeof(memhob)) < 0) return -1; } return 0; } static int add_vcpus_hob(void* hob_buf, unsigned long vcpus) { return hob_add(hob_buf, HOB_TYPE_NR_VCPU, &vcpus, sizeof(vcpus)); } static int add_nvram_hob(void *hob_buf, unsigned long nvram_addr) { return hob_add(hob_buf, HOB_TYPE_NVRAM, &nvram_addr, sizeof(nvram_addr)); } static const unsigned char config_pal_bus_get_features_data[24] = { 0, 0, 0, 32, 0, 0, 240, 189, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_cache_summary[16] = { 3, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_mem_attrib[8] = { 241, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_cache_info[152] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 4, 6, 7, 255, 1, 0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6, 7, 0, 1, 0, 1, 0, 64, 0, 0, 12, 12, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 8, 7, 7, 255, 7, 0, 11, 0, 0, 16, 0, 12, 17, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 8, 7, 7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 254, 255, 255, 255, 255, 255, 255, 255, 2, 8, 7, 7, 7, 5, 9, 11, 0, 0, 4, 0, 12, 15, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 12, 7, 7, 7, 14, 1, 3, 0, 0, 192, 0, 12, 20, 49, 0 }; static const unsigned char config_pal_cache_prot_info[200] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 45, 0, 16, 8, 0, 76, 12, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 16, 4, 0, 76, 44, 68, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 16, 8, 0, 81, 44, 72, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 254, 255, 255, 255, 255, 255, 255, 255, 32, 0, 112, 12, 0, 79, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 0, 160, 12, 0, 84, 124, 76, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_debug_info[16] = { 2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_fixed_addr[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_freq_base[8] = { 109, 219, 182, 13, 0, 0, 0, 0 }; static const unsigned char config_pal_freq_ratios[24] = { 11, 1, 0, 0, 77, 7, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 4, 0, 0, 0, 7, 0, 0, 0 }; static const unsigned char config_pal_halt_info[64] = { 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_perf_mon_info[136] = { 12, 47, 18, 8, 0, 0, 0, 0, 241, 255, 0, 0, 255, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 241, 255, 0, 0, 223, 0, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 240, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_proc_get_features[104] = { 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 6, 64, 49, 0, 0, 0, 0, 64, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 231, 0, 0, 0, 0, 0, 0, 0, 228, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_ptce_info[24] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_register_info[64] = { 255, 0, 47, 127, 17, 17, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 255, 208, 128, 238, 238, 0, 0, 248, 255, 255, 255, 255, 255, 0, 0, 7, 3, 251, 3, 0, 0, 0, 0, 255, 7, 3, 0, 0, 0, 0, 0, 248, 252, 4, 252, 255, 255, 255, 255, 2, 248, 252, 255, 255, 255, 255, 255 }; static const unsigned char config_pal_rse_info[16] = { 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_test_info[48] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_vm_summary[16] = { 101, 18, 15, 2, 7, 7, 4, 2, 59, 18, 0, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_vm_info[104] = { 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 32, 32, 0, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 128, 128, 0, 4, 0, 0, 0, 0, 112, 85, 0, 0, 0, 0, 0 }; static const unsigned char config_pal_vm_page_size[16] = { 0, 112, 85, 21, 0, 0, 0, 0, 0, 112, 85, 21, 0, 0, 0, 0 }; typedef struct{ hob_type_t type; void* data; unsigned long size; } hob_batch_t; static const hob_batch_t hob_batch[]={ { HOB_TYPE_PAL_BUS_GET_FEATURES_DATA, &config_pal_bus_get_features_data, sizeof(config_pal_bus_get_features_data) }, { HOB_TYPE_PAL_CACHE_SUMMARY, &config_pal_cache_summary, sizeof(config_pal_cache_summary) }, { HOB_TYPE_PAL_MEM_ATTRIB, &config_pal_mem_attrib, sizeof(config_pal_mem_attrib) }, { HOB_TYPE_PAL_CACHE_INFO, &config_pal_cache_info, sizeof(config_pal_cache_info) }, { HOB_TYPE_PAL_CACHE_PROT_INFO, &config_pal_cache_prot_info, sizeof(config_pal_cache_prot_info) }, { HOB_TYPE_PAL_DEBUG_INFO, &config_pal_debug_info, sizeof(config_pal_debug_info) }, { HOB_TYPE_PAL_FIXED_ADDR, &config_pal_fixed_addr, sizeof(config_pal_fixed_addr) }, { HOB_TYPE_PAL_FREQ_BASE, &config_pal_freq_base, sizeof(config_pal_freq_base) }, { HOB_TYPE_PAL_FREQ_RATIOS, &config_pal_freq_ratios, sizeof(config_pal_freq_ratios) }, { HOB_TYPE_PAL_HALT_INFO, &config_pal_halt_info, sizeof(config_pal_halt_info) }, { HOB_TYPE_PAL_PERF_MON_INFO, &config_pal_perf_mon_info, sizeof(config_pal_perf_mon_info) }, { HOB_TYPE_PAL_PROC_GET_FEATURES, &config_pal_proc_get_features, sizeof(config_pal_proc_get_features) }, { HOB_TYPE_PAL_PTCE_INFO, &config_pal_ptce_info, sizeof(config_pal_ptce_info) }, { HOB_TYPE_PAL_REGISTER_INFO, &config_pal_register_info, sizeof(config_pal_register_info) }, { HOB_TYPE_PAL_RSE_INFO, &config_pal_rse_info, sizeof(config_pal_rse_info) }, { HOB_TYPE_PAL_TEST_INFO, &config_pal_test_info, sizeof(config_pal_test_info) }, { HOB_TYPE_PAL_VM_SUMMARY, &config_pal_vm_summary, sizeof(config_pal_vm_summary) }, { HOB_TYPE_PAL_VM_INFO, &config_pal_vm_info, sizeof(config_pal_vm_info) }, { HOB_TYPE_PAL_VM_PAGE_SIZE, &config_pal_vm_page_size, sizeof(config_pal_vm_page_size) }, }; static int add_pal_hob(void* hob_buf) { int i; for (i = 0; i < sizeof(hob_batch)/sizeof(hob_batch_t); i++) { if (hob_add(hob_buf, hob_batch[i].type, hob_batch[i].data, hob_batch[i].size) < 0) return -1; } return 0; } // The most significant bit of nvram file descriptor: // 1: valid; 0: invalid #define VALIDATE_NVRAM_FD(x) ((1UL<<(sizeof(x)*8 - 1)) | x) #define IS_VALID_NVRAM_FD(x) ((uint64_t)x >> (sizeof(x)*8 - 1)) static uint64_t nvram_init(xc_interface *xch, const char *nvram_path) { uint64_t fd = 0; fd = open(nvram_path, O_CREAT|O_RDWR, 0644); if ( fd < 0 ) { PERROR("Nvram open failed at %s. Guest will boot without" " nvram support!\n", nvram_path); return -1; } return VALIDATE_NVRAM_FD(fd); } static int copy_from_nvram_to_GFW(xc_interface *xch, uint32_t dom, int nvram_fd) { unsigned int nr_pages = NVRAM_SIZE >> PAGE_SHIFT; struct stat file_stat; char buf[NVRAM_SIZE] = {0}; if ( fstat(nvram_fd, &file_stat) < 0 ) { PERROR("Cannot get Nvram file info! Guest will boot without " "nvram support!\n"); return -1; } if ( 0 == file_stat.st_size ) { DPRINTF("Nvram file create successful!\n"); return 0; } if ( read(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE ) { PERROR("Load nvram fail. guest will boot without" " nvram support!\n"); return -1; } return xc_ia64_copy_to_domain_pages(xch, dom, buf, NVRAM_START >> PAGE_SHIFT, nr_pages); } /* *Check is the address where NVRAM data located valid */ static int is_valid_address(xc_interface *xch, void *addr) { struct nvram_save_addr *p = (struct nvram_save_addr *)addr; if ( p->signature == NVRAM_VALID_SIG ) return 1; else { PERROR("Invalid nvram signature. Nvram save failed!"); return 0; } } /* * GFW use 4k page. when doing foreign map, we should 16k align * the address and map one more page to guarantee all 64k nvram data * can be got. */ static int copy_from_GFW_to_nvram(xc_interface *xch, uint32_t dom, int nvram_fd) { xen_pfn_t *pfn_list = NULL; char *tmp_ptr = NULL; unsigned int nr_pages = 0; uint64_t addr_from_GFW_4k_align = 0; uint32_t offset = 0; uint64_t nvram_base_addr = 0; char buf[NVRAM_SIZE] = {0}; int i; // map one more page nr_pages = (NVRAM_SIZE + PAGE_SIZE) >> PAGE_SHIFT; pfn_list = (xen_pfn_t *)malloc(sizeof(xen_pfn_t) * nr_pages); if ( NULL == pfn_list ) { PERROR("Cannot allocate memory for nvram save!"); close(nvram_fd); return -1; } /* * GFW allocate memory dynamicly to save nvram data * and save address of the dynamic memory at NVRAM_START. * To save nvram data to file, we must get the dynamic * memory address first. */ pfn_list[0] = NVRAM_START >> PAGE_SHIFT; tmp_ptr = (char *)xc_map_foreign_range(xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, pfn_list[0]); if ( NULL == tmp_ptr ) { PERROR("Cannot get nvram data from GFW!"); free(pfn_list); close(nvram_fd); return -1; } /* Check is NVRAM data vaild */ if ( !is_valid_address(xch, tmp_ptr) ) { free(pfn_list); munmap(tmp_ptr, PAGE_SIZE); close(nvram_fd); return -1; } addr_from_GFW_4k_align = ((struct nvram_save_addr *)tmp_ptr)->addr; munmap(tmp_ptr, PAGE_SIZE); // align address to 16k offset = addr_from_GFW_4k_align % ( 16 * MEM_K ); addr_from_GFW_4k_align = addr_from_GFW_4k_align - offset; for ( i=0; i<nr_pages; i++ ) pfn_list[i] = (addr_from_GFW_4k_align >> PAGE_SHIFT) + i; tmp_ptr = (char *)xc_map_foreign_pages(xch, dom, PROT_READ | PROT_WRITE, pfn_list, nr_pages); if ( NULL == tmp_ptr ) { PERROR("Cannot get nvram data from GFW!"); free(pfn_list); close(nvram_fd); return -1; } // calculate nvram data base addrees nvram_base_addr = (uint64_t)(tmp_ptr + offset); memcpy(buf, (void *)nvram_base_addr, NVRAM_SIZE); free(pfn_list); munmap(tmp_ptr, NVRAM_SIZE + PAGE_SIZE); lseek(nvram_fd, 0, SEEK_SET); if ( write(nvram_fd, buf, NVRAM_SIZE) != NVRAM_SIZE ) { PERROR("Save to nvram fail!"); return -1; } close(nvram_fd); DPRINTF("Nvram save successful!\n"); return 0; } int xc_ia64_save_to_nvram(xc_interface *xch, uint32_t dom) { xc_dominfo_t info; uint64_t nvram_fd = 0; if ( xc_domain_getinfo(xch, dom, 1, &info) != 1 ) { PERROR("Could not get info for domain"); return -1; } if ( !info.hvm ) return 0; xc_get_hvm_param(xch, dom, HVM_PARAM_NVRAM_FD, &nvram_fd); if ( !IS_VALID_NVRAM_FD(nvram_fd) ) PERROR("Nvram not initialized. Nvram save failed!"); else copy_from_GFW_to_nvram(xch, dom, (int)nvram_fd); // although save to nvram maybe fail, we don't return any error number // to Xend. This is quite logical because damage of NVRAM on native would // not block OS's executive path. Return error number will cause an // exception of Xend and block XenU when it destroy. return 0; } #define NVRAM_DIR "/var/lib/xen/nvram/" #define NVRAM_FILE_PREFIX "nvram_" int xc_ia64_nvram_init(xc_interface *xch, char *dom_name, uint32_t dom) { uint64_t nvram_fd; char nvram_path[PATH_MAX] = NVRAM_DIR; if ( access(nvram_path, R_OK|W_OK|X_OK) == -1 ) { if ( errno != ENOENT ) { PERROR("Error stat'ing NVRAM dir %s.", nvram_path); return -1; } if ( mkdir(nvram_path, 0755) == -1 ) { PERROR("Unable to create NVRAM store directory %s.", nvram_path); return -1; } } if ( access(nvram_path, R_OK|W_OK|X_OK) == -1 ) { errno = EACCES; PERROR("No RWX permission to NVRAM store directory %s.", nvram_path); return -1; } if ( strlen(nvram_path) + strlen(NVRAM_FILE_PREFIX) + strlen(dom_name) + 1 > sizeof(nvram_path) ) { PERROR("Nvram file path is too long!"); return -1; } strcat(nvram_path, NVRAM_FILE_PREFIX); strcat(nvram_path, dom_name); nvram_fd = nvram_init(xch, nvram_path); if ( nvram_fd == (uint64_t)(-1) ) { xc_set_hvm_param(xch, dom, HVM_PARAM_NVRAM_FD, 0); return -1; } xc_set_hvm_param(xch, dom, HVM_PARAM_NVRAM_FD, nvram_fd); return 0; } #define GFW_PAGES (GFW_SIZE >> PAGE_SHIFT) #define VGA_START_PAGE (VGA_IO_START >> PAGE_SHIFT) #define VGA_END_PAGE ((VGA_IO_START + VGA_IO_SIZE) >> PAGE_SHIFT) static void xc_ia64_setup_md(efi_memory_desc_t *md, unsigned long start, unsigned long end) { md->type = EFI_CONVENTIONAL_MEMORY; md->pad = 0; md->phys_addr = start; md->virt_addr = 0; md->num_pages = (end - start) >> EFI_PAGE_SHIFT; md->attribute = EFI_MEMORY_WB; } static inline unsigned long min(unsigned long lhs, unsigned long rhs) { return (lhs < rhs)? lhs: rhs; } static int xc_ia64_setup_memmap_info(xc_interface *xch, uint32_t dom, unsigned long dom_memsize, /* in bytes */ unsigned long *pfns_special_pages, unsigned long nr_special_pages, unsigned long memmap_info_pfn, unsigned long memmap_info_num_pages) { xen_ia64_memmap_info_t* memmap_info; efi_memory_desc_t *md; uint64_t nr_mds; memmap_info = xc_map_foreign_range(xch, dom, PAGE_SIZE * memmap_info_num_pages, PROT_READ | PROT_WRITE, memmap_info_pfn); if (memmap_info == NULL) { PERROR("Could not map memmmap_info page."); return -1; } memset(memmap_info, 0, PAGE_SIZE * memmap_info_num_pages); /* * [0, VGA_IO_START = 0xA0000) * [VGA_IO_START + VGA_IO_SIZE = 0xC0000, MMIO_START = 3GB) * [IO_PAGE_START (> 3GB), IO_PAGE_START + IO_PAGE_SIZE) * [STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE) * [BUFFER_IO_PAGE_START, BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE) * [BUFFER_PIO_PAGE_START, BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE) * [memmap_info_pfn << PAGE_SHIFT, * (memmap_info_pfn << PAGE_SHIFT) + PAGE_SIZE) * [GFW_START=4GB - GFW_SIZE, GFW_START + GFW_SIZE = 4GB) * [4GB, ...) */ md = (efi_memory_desc_t*)&memmap_info->memdesc; xc_ia64_setup_md(md, 0, min(VGA_IO_START, dom_memsize)); md++; if (dom_memsize > VGA_IO_START) { xc_ia64_setup_md(md, VGA_IO_START + VGA_IO_SIZE, min(MMIO_START, dom_memsize + VGA_IO_SIZE)); md++; } xc_ia64_setup_md(md, IO_PAGE_START, IO_PAGE_START + IO_PAGE_SIZE); md++; xc_ia64_setup_md(md, STORE_PAGE_START, STORE_PAGE_START + STORE_PAGE_SIZE); md++; xc_ia64_setup_md(md, BUFFER_IO_PAGE_START, BUFFER_IO_PAGE_START + BUFFER_IO_PAGE_SIZE); md++; xc_ia64_setup_md(md, BUFFER_PIO_PAGE_START, BUFFER_PIO_PAGE_START + BUFFER_PIO_PAGE_SIZE); md++; xc_ia64_setup_md(md, memmap_info_pfn << PAGE_SHIFT, (memmap_info_pfn << PAGE_SHIFT) + PAGE_SIZE * memmap_info_num_pages); md++; xc_ia64_setup_md(md, GFW_START, GFW_START + GFW_SIZE); md++; if (dom_memsize + VGA_IO_SIZE > MMIO_START) { xc_ia64_setup_md(md, 4 * MEM_G, dom_memsize + VGA_IO_SIZE + (1 * MEM_G)); md++; } nr_mds = md - (efi_memory_desc_t*)&memmap_info->memdesc; assert(nr_mds <= (PAGE_SIZE * memmap_info_num_pages - offsetof(typeof(*memmap_info), memdesc))/sizeof(*md)); memmap_info->efi_memmap_size = nr_mds * sizeof(*md); memmap_info->efi_memdesc_size = sizeof(*md); memmap_info->efi_memdesc_version = EFI_MEMORY_DESCRIPTOR_VERSION; munmap(memmap_info, PAGE_SIZE * memmap_info_num_pages); return 0; } /* setup shared_info page */ static int xc_ia64_setup_shared_info(xc_interface *xch, uint32_t dom, unsigned long shared_info_pfn, unsigned long memmap_info_pfn, unsigned long memmap_info_num_pages) { shared_info_t *shared_info; shared_info = xc_map_foreign_range(xch, dom, PAGE_SIZE, PROT_READ | PROT_WRITE, shared_info_pfn); if (shared_info == NULL) { PERROR("Could not map shared_info"); return -1; } memset(shared_info, 0, sizeof(*shared_info)); shared_info->arch.memmap_info_num_pages = memmap_info_num_pages; shared_info->arch.memmap_info_pfn = memmap_info_pfn; munmap(shared_info, PAGE_SIZE); return 0; } /* * In this function, we will allocate memory and build P2M/M2P table for VTI * guest. Frist, a pfn list will be initialized discontiguous, normal memory * begins with 0, GFW memory and other five pages at their place defined in * xen/include/public/arch-ia64.h xc_domain_populate_physmap_exact() called * five times, to set parameter 'extent_order' to different value, this is * convenient to allocate discontiguous memory with different size. */ static int setup_guest(xc_interface *xch, uint32_t dom, unsigned long memsize, char *image, unsigned long image_size) { xen_pfn_t *pfn_list; unsigned long dom_memsize = memsize; unsigned long nr_pages = memsize >> PAGE_SHIFT; unsigned long vcpus; unsigned long nr_special_pages; unsigned long memmap_info_pfn; unsigned long memmap_info_num_pages; unsigned long nvram_start = NVRAM_START, nvram_fd = 0; int rc; unsigned long i; unsigned long pfn; const struct hvm_special_page { int param; xen_pfn_t pfn; } special_pages[] = { // pfn-sorted array { HVM_PARAM_IOREQ_PFN, IO_PAGE_START >> PAGE_SHIFT}, { HVM_PARAM_STORE_PFN, STORE_PAGE_START >> PAGE_SHIFT}, { HVM_PARAM_BUFIOREQ_PFN, BUFFER_IO_PAGE_START >> PAGE_SHIFT}, { HVM_PARAM_BUFPIOREQ_PFN, BUFFER_PIO_PAGE_START >> PAGE_SHIFT}, }; DECLARE_DOMCTL; if ((image_size > 12 * MEM_M) || (image_size & (PAGE_SIZE - 1))) { PERROR("Guest firmware size is incorrect [%ld]?", image_size); return -1; } pfn_list = malloc(nr_pages * sizeof(xen_pfn_t)); if (pfn_list == NULL) { PERROR("Could not allocate memory."); return -1; } // // Populate // [0, VGA_IO_START) (VGA_IO_SIZE hole) // [VGA_IO_START + VGA_IO_SIZE, MMIO_START) (1GB hole) // [4GB, end) // i = 0; for (pfn = 0; pfn < MIN((dom_memsize >> PAGE_SHIFT), VGA_START_PAGE); pfn++) pfn_list[i++] = pfn; for (pfn = VGA_END_PAGE; pfn < (MIN(dom_memsize + VGA_IO_SIZE, MMIO_START) >> PAGE_SHIFT); pfn++) pfn_list[i++] = pfn; for (pfn = ((4 * MEM_G) >> PAGE_SHIFT); pfn < ((dom_memsize + VGA_IO_SIZE + 1 * MEM_G) >> PAGE_SHIFT); pfn++) pfn_list[i++] = pfn; rc = xc_domain_populate_physmap_exact(xch, dom, nr_pages, 0, 0, &pfn_list[0]); if (rc != 0) { PERROR("Could not allocate normal memory for Vti guest."); goto error_out; } // We allocate additional pfn for GFW and other five pages, so // the pfn_list is not contiguous. Due to this we must support // old interface xc_ia64_get_pfn_list(). for (i = 0; i < GFW_PAGES; i++) pfn_list[i] = (GFW_START >> PAGE_SHIFT) + i; rc = xc_domain_populate_physmap_exact(xch, dom, GFW_PAGES, 0, 0, &pfn_list[0]); if (rc != 0) { PERROR("Could not allocate GFW memory for Vti guest."); goto error_out; } for (i = 0; i < sizeof(special_pages) / sizeof(special_pages[0]); i++) pfn_list[i] = special_pages[i].pfn; nr_special_pages = i; memmap_info_pfn = pfn_list[nr_special_pages - 1] + 1; memmap_info_num_pages = 1; pfn_list[nr_special_pages] = memmap_info_pfn; nr_special_pages++; rc = xc_domain_populate_physmap_exact(xch, dom, nr_special_pages, 0, 0, &pfn_list[0]); if (rc != 0) { PERROR("Could not allocate IO page or store page or buffer io page."); goto error_out; } domctl.u.arch_setup.flags = 0; domctl.u.arch_setup.bp = 0; domctl.u.arch_setup.maxmem = GFW_START + GFW_SIZE; if (dom_memsize + VGA_IO_SIZE > MMIO_START) domctl.u.arch_setup.maxmem = dom_memsize + VGA_IO_SIZE + 1 * MEM_G; domctl.cmd = XEN_DOMCTL_arch_setup; domctl.domain = (domid_t)dom; if (xc_domctl(xch, &domctl)) goto error_out; // Load guest firmware if (xc_ia64_copy_to_domain_pages(xch, dom, image, (GFW_START + GFW_SIZE - image_size) >> PAGE_SHIFT, image_size >> PAGE_SHIFT)) { PERROR("Could not load guest firmware into domain"); goto error_out; } domctl.cmd = XEN_DOMCTL_getdomaininfo; domctl.domain = (domid_t)dom; if (xc_domctl(xch, &domctl) < 0) { PERROR("Could not get info on domain"); goto error_out; } if (xc_ia64_setup_memmap_info(xch, dom, dom_memsize, pfn_list, nr_special_pages, memmap_info_pfn, memmap_info_num_pages)) { PERROR("Could not build memmap info"); goto error_out; } if (xc_ia64_setup_shared_info(xch, dom, domctl.u.getdomaininfo.shared_info_frame, memmap_info_pfn, memmap_info_num_pages)) { PERROR("Could not setup shared_info"); goto error_out; } xc_get_hvm_param(xch, dom, HVM_PARAM_NVRAM_FD, &nvram_fd); if ( !IS_VALID_NVRAM_FD(nvram_fd) ) nvram_start = 0; else if ( copy_from_nvram_to_GFW(xch, dom, (int)nvram_fd ) == -1 ) { nvram_start = 0; close(nvram_fd); } vcpus = domctl.u.getdomaininfo.max_vcpu_id + 1; // Hand-off state passed to guest firmware if (xc_ia64_build_hob(xch, dom, dom_memsize, vcpus, nvram_start) < 0) { PERROR("Could not build hob"); goto error_out; } // zero clear all special pages for (i = 0; i < sizeof(special_pages) / sizeof(special_pages[0]); i++) { xc_set_hvm_param(xch, dom, special_pages[i].param, special_pages[i].pfn); if (xc_clear_domain_page(xch, dom, special_pages[i].pfn)) goto error_out; } free(pfn_list); return 0; error_out: return -1; } int xc_hvm_build(xc_interface *xch, uint32_t domid, const struct xc_hvm_build_args *args) { vcpu_guest_context_any_t st_ctxt_any; vcpu_guest_context_t *ctxt = &st_ctxt_any.c; char *image = NULL; unsigned long image_size; image = xc_read_image(xch, args->image_file_name, &image_size); if (image == NULL) { PERROR("Could not read guest firmware image %s", image_name); goto error_out; } image_size = (image_size + PAGE_SIZE - 1) & PAGE_MASK; if (setup_guest(xch, domid, (unsigned long)args->mem_size, image, image_size) < 0) { ERROR("Error constructing guest OS"); goto error_out; } free(image); memset(&st_ctxt_any, 0, sizeof(st_ctxt_any)); ctxt->regs.ip = 0x80000000ffffffb0UL; ctxt->regs.ar.fpsr = xc_ia64_fpsr_default(); ctxt->regs.cr.itir = 14 << 2; ctxt->regs.psr = IA64_PSR_AC | IA64_PSR_BN; ctxt->regs.cr.dcr = 0; ctxt->regs.cr.pta = 15 << 2; return xc_vcpu_setcontext(xch, domid, 0, &st_ctxt_any); error_out: free(image); return -1; } /* xc_hvm_build_target_mem: * Create a domain for a pre-ballooned virtualized Linux, using * files/filenames. If target < memsize, domain is created with * memsize pages marked populate-on-demand, and with a PoD cache size * of target. If target == memsize, pages are populated normally. * * XXX:PoD isn't supported yet so setting target does nothing. */ int xc_hvm_build_target_mem(xc_interface *xch, uint32_t domid, int memsize, int target, const char *image_name) { struct xc_hvm_build_args args; args.mem_size = (uint64_t)memsize << 20; args.mem_target = (uint64_t)target << 20; args.image_file_name = image_name; return xc_hvm_build(xch, domid, &args); } /* * From asm/pgtable.h */ #define _PAGE_P_BIT 0 #define _PAGE_A_BIT 5 #define _PAGE_D_BIT 6 #define _PAGE_P (1 << _PAGE_P_BIT) /* page present bit */ #define _PAGE_A (1 << _PAGE_A_BIT) /* page accessed bit */ #define _PAGE_D (1 << _PAGE_D_BIT) /* page dirty bit */ #define _PAGE_MA_WB (0x0 << 2) /* write back memory attribute */ #define _PAGE_MA_UC (0x4 << 2) /* uncacheable memory attribute */ #define _PAGE_AR_RW (2 << 9) /* read & write */ int xc_ia64_set_os_type(xc_interface *xch, char *guest_os_type, uint32_t dom) { DECLARE_DOMCTL; domctl.cmd = XEN_DOMCTL_set_opt_feature; domctl.domain = (domid_t)dom; if (!guest_os_type || !strlen(guest_os_type) || !strcmp("default", guest_os_type)) { /* Nothing */ return 0; } else if (!strcmp("windows", guest_os_type)) { DPRINTF("Enabling Windows guest OS optimizations\n"); /* Windows identity maps regions 4 & 5 */ domctl.u.set_opt_feature.optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG4; domctl.u.set_opt_feature.optf.on = XEN_IA64_OPTF_ON; domctl.u.set_opt_feature.optf.pgprot = (_PAGE_P | _PAGE_A | _PAGE_D | _PAGE_MA_WB | _PAGE_AR_RW); domctl.u.set_opt_feature.optf.key = 0; if (xc_domctl(xch, &domctl)) PERROR("Failed to set region 4 identity mapping for Windows " "guest OS type.\n"); domctl.u.set_opt_feature.optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG5; domctl.u.set_opt_feature.optf.on = XEN_IA64_OPTF_ON; domctl.u.set_opt_feature.optf.pgprot = (_PAGE_P | _PAGE_A | _PAGE_D | _PAGE_MA_UC | _PAGE_AR_RW); domctl.u.set_opt_feature.optf.key = 0; if (xc_domctl(xch, &domctl)) PERROR("Failed to set region 5 identity mapping for Windows " "guest OS type.\n"); return 0; } else if (!strcmp("linux", guest_os_type)) { DPRINTF("Enabling Linux guest OS optimizations\n"); /* Linux identity maps regions 7 */ domctl.u.set_opt_feature.optf.cmd = XEN_IA64_OPTF_IDENT_MAP_REG7; domctl.u.set_opt_feature.optf.on = XEN_IA64_OPTF_ON; domctl.u.set_opt_feature.optf.pgprot = (_PAGE_P | _PAGE_A | _PAGE_D | _PAGE_MA_WB | _PAGE_AR_RW); domctl.u.set_opt_feature.optf.key = 0; if (xc_domctl(xch, &domctl)) PERROR("Failed to set region 7 identity mapping for Linux " "guest OS type.\n"); return 0; } DPRINTF("Unknown guest_os_type (%s), using defaults\n", guest_os_type); return 0; } /* * Local variables: * mode: C * c-set-style: "BSD" * c-basic-offset: 4 * tab-width: 4 * indent-tabs-mode: nil * End: */