diff --git a/doc/hifive-unmatched-revb.txt b/doc/hifive-unmatched-revb.txt new file mode 100644 index 00000000..27c7cf9c --- /dev/null +++ b/doc/hifive-unmatched-revb.txt @@ -0,0 +1,35 @@ +Booting Yggdrasil OS on SiFive HiFive Unmatched Rev B RISC-V board: + +* TODO: proper format for initrd image + +Prerequisites: + +* OpenSBI + u-boot (can use the u-boot from the Freedom U SDK that comes with the board) +* yggdrasil-kernel.bin +* initrd.img + +Steps: + +1. Copy yggdrasil-kernel.bin and initrd.img into some directory and start a TFTP server there +2. Connect to HFU's serial port, ethernet and enter u-boot +3. Run the following commands in u-boot: + +### If using DHCP + +=> setenv autoload no +=> setenv initrd_addr_r 0x90000000 +=> dhcp +=> tftpboot ${initrd_addr_r} :initrd.img +=> tftpboot ${loadaddr} :yggdrasil-kernel.bin +=> tftpboot ${fdt_addr_r} :hifive-unmatched-a00.dtb +=> fdt resize +=> booti ${loadaddr} ${initrd_addr_r}:60000000 ${fdt_addr_r} + +Two-liner (server is 13.0.0.1, board is 13.0.0.2): + +setenv ipaddr 13.0.0.2;setenv initrd_addr_r 0x90000000;tftpboot ${initrd_addr_r} 13.0.0.1:initrd.img;tftpboot ${loadaddr} 13.0.0.1:yggdrasil-kernel.bin;tftpboot ${fdt_addr_r} 13.0.0.1:hifive-unmatched-a00.dtb;fdt resize +booti ${loadaddr} ${initrd_addr_r}:60000000 ${fdt_addr_r} + +One-liner without initrd + +setenv ipaddr 13.0.0.2;tftpboot ${loadaddr} 13.0.0.1:yggdrasil-kernel.bin;tftpboot ${fdt_addr_r} 13.0.0.1:hifive-unmatched-a00.dtb;fdt resize;booti ${loadaddr} - ${fdt_addr_r} diff --git a/etc/dtb/riscv64/hifive-unmatched-a00.dts b/etc/dtb/riscv64/hifive-unmatched-a00.dts new file mode 100644 index 00000000..a57925be --- /dev/null +++ b/etc/dtb/riscv64/hifive-unmatched-a00.dts @@ -0,0 +1,237 @@ +/dts-v1/; + +#define CLK_COREPLL 0 +#define CLK_DDRPLL 1 +#define CLK_GEMGXLPLL 2 +#define CLK_DVFSCOREPLL 3 +#define CLK_HFPCLKPLL 4 +#define CLK_CLTXPLL 5 +#define CLK_TLCLK 6 +#define CLK_PCLK 7 +#define CLK_PCIE_AUX 8 + +/ { + #address-cells = <2>; + #size-cells = <2>; + compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000", "sifive,fu740"; + model = "SiFive HiFive Unmatched"; + + aliases { + serial0 = "/soc/serial@10010000"; + serial1 = "/soc/serial@10011000"; + }; + + chosen { + stdout-path = "serial0"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <1000000>; + + cpu0: cpu@0 { + compatible = "sifive,bullet0", "riscv"; + device_type = "cpu"; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <16384>; + next-level-cache = <&ccache>; + reg = <0>; + riscv,isa = "rv64imac"; + status = "disabled"; + + cpu0_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu1: cpu@1 { + compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + device_type = "cpu"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <32768>; + i-tlb-sets = <1>; + i-tlb-size = <40>; + d-tlb-sets = <1>; + d-tlb-size = <40>; + mmu-type = "riscv,sv39"; + next-level-cache = <&ccache>; + reg = <1>; + riscv,isa = "rv64imafdc"; + tlb-split; + + cpu1_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu2: cpu@2 { + compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + device_type = "cpu"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <40>; + i-tlb-sets = <1>; + i-tlb-size = <40>; + mmu-type = "riscv,sv39"; + next-level-cache = <&ccache>; + reg = <2>; + riscv,isa = "rv64imafdc"; + tlb-split; + + cpu2_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu3: cpu@3 { + compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + device_type = "cpu"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <40>; + i-tlb-sets = <1>; + i-tlb-size = <40>; + mmu-type = "riscv,sv39"; + next-level-cache = <&ccache>; + reg = <3>; + riscv,isa = "rv64imafdc"; + tlb-split; + + cpu3_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu4: cpu@4 { + compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + device_type = "cpu"; + d-cache-block-size = <64>; + d-cache-sets = <64>; + d-cache-size = <32768>; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <32768>; + d-tlb-sets = <1>; + d-tlb-size = <40>; + i-tlb-sets = <1>; + i-tlb-size = <40>; + mmu-type = "riscv,sv39"; + next-level-cache = <&ccache>; + reg = <4>; + riscv,isa = "rv64imafdc"; + tlb-split; + + cpu4_intc: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + }; + + soc { + #address-cells = <2>; + #size-cells = <2>; + compatible = "simple-bus"; + ranges; + + plic: interrupt-controller@c000000 { + #interrupt-cells = <1>; + #address-cells = <0>; + compatible = "sifive,fu540-c000-plic", "sifive,plic-1.0.0"; + reg = <0x00 0xc000000 0x00 0x4000000>; + riscv,ndev = <69>; + interrupt-controller; + interrupts-extended = <&cpu0_intc 0xffffffff>, + <&cpu1_intc 0xffffffff>, + <&cpu1_intc 0x09>, + <&cpu2_intc 0xffffffff>, + <&cpu2_intc 0x09>, + <&cpu3_intc 0xffffffff>, + <&cpu3_intc 0x09>, + <&cpu4_intc 0xffffffff>, + <&cpu4_intc 0x09>; + }; + + prci: clock-controller@10000000 { + compatible = "sifive,fu740-c000-prci"; + reg = <0x00 0x10000000 0x00 0x1000>; + clocks = <&clk_hfclk>, <&clk_rtcclk>; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + uart0: serial@10010000 { + compatible = "sifive,fu740-c000-uart", "sifive,uart0"; + reg = <0x00 0x10010000 0x00 0x1000>; + interrupt-parent = <&plic>; + interrupts = <39>; + clocks = <&prci CLK_PCLK>; + status = "okay"; + }; + + uart1: serial@10011000 { + compatible = "sifive,fu740-c000-uart", "sifive,uart0"; + reg = <0x00 0x10011000 0x00 0x1000>; + interrupt-parent = <&plic>; + interrupts = <40>; + clocks = <&prci CLK_PCLK>; + status = "disabled"; + }; + + ccache: cache-controller@2010000 { + compatible = "sifive,fu740-c000-ccache", "cache"; + cache-block-size = <64>; + cache-level = <2>; + cache-sets = <2048>; + cache-size = <0x200000>; + cache-unified; + interrupt-parent = <&plic>; + interrupts = <0x13>, <0x15>, <0x16>, <0x14>; + reg = <0x00 0x2010000 0x00 0x1000>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00 0x80000000 0x04 0x00>; + }; + + clk_hfclk: hfclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <26000000>; + clock-output-names = "hfclk"; + }; + + clk_rtcclk: rtcclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <1000000>; + clock-output-names = "rtcclk"; + }; +}; diff --git a/etc/raw-dtb/hifive-unmatched-a00.dtb b/etc/raw-dtb/hifive-unmatched-a00.dtb new file mode 100644 index 00000000..d288a57d Binary files /dev/null and b/etc/raw-dtb/hifive-unmatched-a00.dtb differ diff --git a/etc/raw-dtb/hifive-unmatched-a00.dts b/etc/raw-dtb/hifive-unmatched-a00.dts new file mode 100644 index 00000000..92f029cb --- /dev/null +++ b/etc/raw-dtb/hifive-unmatched-a00.dts @@ -0,0 +1,577 @@ +/dts-v1/; + +/ { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "sifive,hifive-unmatched-a00", "sifive,fu740-c000", "sifive,fu740"; + model = "SiFive HiFive Unmatched"; + + aliases { + serial0 = "/soc/serial@10010000"; + serial1 = "/soc/serial@10011000"; + ethernet0 = "/soc/ethernet@10090000"; + }; + + chosen { + stdout-path = "serial0"; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + timebase-frequency = <0xf4240>; + + cpu@0 { + compatible = "sifive,bullet0", "riscv"; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x4000>; + next-level-cache = <0x01>; + reg = <0x00>; + riscv,isa = "rv64imac"; + status = "disabled"; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + phandle = <0x02>; + }; + }; + + cpu@1 { + compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x01>; + reg = <0x01>; + riscv,isa = "rv64imafdc"; + tlb-split; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + phandle = <0x03>; + }; + }; + + cpu@2 { + compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x01>; + reg = <0x02>; + riscv,isa = "rv64imafdc"; + tlb-split; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + phandle = <0x04>; + }; + }; + + cpu@3 { + compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x01>; + reg = <0x03>; + riscv,isa = "rv64imafdc"; + tlb-split; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + phandle = <0x05>; + }; + }; + + cpu@4 { + compatible = "sifive,u74-mc", "sifive,bullet0", "riscv"; + d-cache-block-size = <0x40>; + d-cache-sets = <0x40>; + d-cache-size = <0x8000>; + d-tlb-sets = <0x01>; + d-tlb-size = <0x28>; + device_type = "cpu"; + i-cache-block-size = <0x40>; + i-cache-sets = <0x80>; + i-cache-size = <0x8000>; + i-tlb-sets = <0x01>; + i-tlb-size = <0x28>; + mmu-type = "riscv,sv39"; + next-level-cache = <0x01>; + reg = <0x04>; + riscv,isa = "rv64imafdc"; + tlb-split; + + interrupt-controller { + #interrupt-cells = <0x01>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + phandle = <0x06>; + }; + }; + }; + + soc { + #address-cells = <0x02>; + #size-cells = <0x02>; + compatible = "simple-bus"; + ranges; + + interrupt-controller@c000000 { + #interrupt-cells = <0x01>; + #address-cells = <0x00>; + compatible = "sifive,fu540-c000-plic", "sifive,plic-1.0.0"; + reg = <0x00 0xc000000 0x00 0x4000000>; + riscv,ndev = <0x45>; + interrupt-controller; + interrupts-extended = <0x02 0xffffffff 0x03 0xffffffff 0x03 0x09 0x04 0xffffffff 0x04 0x09 0x05 0xffffffff 0x05 0x09 0x06 0xffffffff 0x06 0x09>; + phandle = <0x09>; + }; + + prci: clock-controller@10000000 { + compatible = "sifive,fu740-c000-prci"; + reg = <0x00 0x10000000 0x00 0x1000>; + clocks = <&clk_hfclk>, <&clk_rtcclk>; + #clock-cells = <0x01>; + #reset-cells = <0x01>; + }; + + serial@10010000 { + compatible = "sifive,fu740-c000-uart", "sifive,uart0"; + reg = <0x00 0x10010000 0x00 0x1000>; + interrupt-parent = <0x09>; + interrupts = <0x27>; + clocks = <&prci 0x07>; + status = "okay"; + }; + + serial@10011000 { + compatible = "sifive,fu740-c000-uart", "sifive,uart0"; + reg = <0x00 0x10011000 0x00 0x1000>; + interrupt-parent = <0x09>; + interrupts = <0x28>; + clocks = <&prci 0x07>; + status = "okay"; + }; + + i2c@10030000 { + compatible = "sifive,fu740-c000-i2c", "sifive,i2c0"; + reg = <0x00 0x10030000 0x00 0x1000>; + interrupt-parent = <0x09>; + interrupts = <0x34>; + clocks = <&prci 0x07>; + reg-shift = <0x02>; + reg-io-width = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + + temperature-sensor@4c { + compatible = "ti,tmp451"; + reg = <0x4c>; + interrupt-parent = <0x0b>; + interrupts = <0x06 0x08>; + }; + + pmic@58 { + compatible = "dlg,da9063"; + reg = <0x58>; + interrupt-parent = <0x0b>; + interrupts = <0x01 0x08>; + interrupt-controller; + + regulators { + + bcore1 { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x4c4b40>; + regulator-max-microamp = <0x4c4b40>; + regulator-always-on; + }; + + bcore2 { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x4c4b40>; + regulator-max-microamp = <0x4c4b40>; + regulator-always-on; + }; + + bpro { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x2625a0>; + regulator-max-microamp = <0x2625a0>; + regulator-always-on; + }; + + bperi { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x16e360>; + regulator-max-microamp = <0x16e360>; + regulator-always-on; + }; + + bmem { + regulator-min-microvolt = <0x124f80>; + regulator-max-microvolt = <0x124f80>; + regulator-min-microamp = <0x2dc6c0>; + regulator-max-microamp = <0x2dc6c0>; + regulator-always-on; + }; + + bio { + regulator-min-microvolt = <0x124f80>; + regulator-max-microvolt = <0x124f80>; + regulator-min-microamp = <0x2dc6c0>; + regulator-max-microamp = <0x2dc6c0>; + regulator-always-on; + }; + + ldo1 { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x186a0>; + regulator-max-microamp = <0x186a0>; + regulator-always-on; + }; + + ldo2 { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo3 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo4 { + regulator-min-microvolt = <0x2625a0>; + regulator-max-microvolt = <0x2625a0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo5 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x186a0>; + regulator-max-microamp = <0x186a0>; + regulator-always-on; + }; + + ldo6 { + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x1b7740>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo7 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo8 { + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + regulator-always-on; + }; + + ldo9 { + regulator-min-microvolt = <0x100590>; + regulator-max-microvolt = <0x100590>; + regulator-min-microamp = <0x30d40>; + regulator-max-microamp = <0x30d40>; + }; + + ldo10 { + regulator-min-microvolt = <0xf4240>; + regulator-max-microvolt = <0xf4240>; + regulator-min-microamp = <0x493e0>; + regulator-max-microamp = <0x493e0>; + }; + + ldo11 { + regulator-min-microvolt = <0x2625a0>; + regulator-max-microvolt = <0x2625a0>; + regulator-min-microamp = <0x493e0>; + regulator-max-microamp = <0x493e0>; + regulator-always-on; + }; + }; + }; + }; + + i2c@10031000 { + compatible = "sifive,fu740-c000-i2c", "sifive,i2c0"; + reg = <0x00 0x10031000 0x00 0x1000>; + interrupt-parent = <0x09>; + interrupts = <0x35>; + clocks = <&prci 0x07>; + reg-shift = <0x02>; + reg-io-width = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + }; + + spi@10040000 { + compatible = "sifive,fu740-c000-spi", "sifive,spi0"; + reg = <0x00 0x10040000 0x00 0x1000 0x00 0x20000000 0x00 0x10000000>; + interrupt-parent = <0x09>; + interrupts = <0x29>; + clocks = <&prci 0x07>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + + flash@0 { + compatible = "issi,is25wp256", "jedec,spi-nor"; + reg = <0x00>; + spi-max-frequency = <0x2faf080>; + m25p,fast-read; + spi-tx-bus-width = <0x04>; + spi-rx-bus-width = <0x04>; + }; + }; + + spi@10041000 { + compatible = "sifive,fu740-c000-spi", "sifive,spi0"; + reg = <0x00 0x10041000 0x00 0x1000 0x00 0x30000000 0x00 0x10000000>; + interrupt-parent = <0x09>; + interrupts = <0x2a>; + clocks = <&prci 0x07>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + }; + + spi@10050000 { + compatible = "sifive,fu740-c000-spi", "sifive,spi0"; + reg = <0x00 0x10050000 0x00 0x1000>; + interrupt-parent = <0x09>; + interrupts = <0x2b>; + clocks = <&prci 0x07>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + + mmc@0 { + compatible = "mmc-spi-slot"; + reg = <0x00>; + spi-max-frequency = <0x1312d00>; + voltage-ranges = <0xce4 0xce4>; + disable-wp; + }; + }; + + macb: ethernet@10090000 { + compatible = "sifive,fu540-c000-gem"; + interrupt-parent = <0x09>; + interrupts = <0x37>; + reg = <0x00 0x10090000 0x00 0x2000 0x00 0x100a0000 0x00 0x1000>; + local-mac-address = [00 00 00 00 00 00]; + clock-names = "pclk", "hclk"; + clocks = <&prci 0x02 &prci 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "okay"; + phy-mode = "gmii"; + phy-handle = <0x0c>; + + ethernet-phy@0 { + reg = <0x00>; + phandle = <0x0c>; + }; + }; + + pwm@10020000 { + compatible = "sifive,fu740-c000-pwm", "sifive,pwm0"; + reg = <0x00 0x10020000 0x00 0x1000>; + interrupt-parent = <0x09>; + interrupts = <0x2c 0x2d 0x2e 0x2f>; + clocks = <&prci 0x07>; + #pwm-cells = <0x03>; + status = "okay"; + phandle = <0x0d>; + }; + + pwm@10021000 { + compatible = "sifive,fu740-c000-pwm", "sifive,pwm0"; + reg = <0x00 0x10021000 0x00 0x1000>; + interrupt-parent = <0x09>; + interrupts = <0x30 0x31 0x32 0x33>; + clocks = <&prci 0x07>; + #pwm-cells = <0x03>; + status = "okay"; + }; + + cache-controller@2010000 { + compatible = "sifive,fu740-c000-ccache", "cache"; + cache-block-size = <0x40>; + cache-level = <0x02>; + cache-sets = <0x800>; + cache-size = <0x200000>; + cache-unified; + interrupt-parent = <0x09>; + interrupts = <0x13 0x15 0x16 0x14>; + reg = <0x00 0x2010000 0x00 0x1000>; + phandle = <0x01>; + }; + + gpio@10060000 { + compatible = "sifive,fu740-c000-gpio", "sifive,gpio0"; + interrupt-parent = <0x09>; + interrupts = <0x17 0x18 0x19 0x1a 0x1b 0x1c 0x1d 0x1e 0x1f 0x20 0x21 0x22 0x23 0x24 0x25 0x26>; + reg = <0x00 0x10060000 0x00 0x1000>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + clocks = <&prci 0x07>; + status = "okay"; + phandle = <0x0b>; + }; + + pcie@e00000000 { + #address-cells = <0x03>; + #interrupt-cells = <0x01>; + #num-lanes = <0x08>; + #size-cells = <0x02>; + compatible = "sifive,fu740-pcie"; + reg = <0x0e 0x00 0x01 0x00 0x0d 0xf0000000 0x00 0x10000000 0x00 0x100d0000 0x00 0x1000>; + reg-names = "dbi", "config", "mgmt"; + device_type = "pci"; + dma-coherent; + bus-range = <0x00 0xff>; + ranges = <0x81000000 0x00 0x60080000 0x00 0x60080000 0x00 0x10000 0x82000000 0x00 0x60090000 0x00 0x60090000 0x00 0xff70000 0x82000000 0x00 0x70000000 0x00 0x70000000 0x00 0x1000000 0xc3000000 0x20 0x00 0x20 0x00 0x20 0x00>; + num-lanes = <0x08>; + interrupts = <0x38 0x39 0x3a 0x3b 0x3c 0x3d 0x3e 0x3f 0x40>; + interrupt-names = "msi", "inta", "intb", "intc", "intd"; + interrupt-parent = <0x09>; + interrupt-map-mask = <0x00 0x00 0x00 0x07>; + interrupt-map = <0x00 0x00 0x00 0x01 0x09 0x39 0x00 0x00 0x00 0x02 0x09 0x3a 0x00 0x00 0x00 0x03 0x09 0x3b 0x00 0x00 0x00 0x04 0x09 0x3c>; + clock-names = "pcie_aux"; + clocks = <&prci 0x08>; + pwren-gpios = <0x0b 0x05 0x00>; + perstn-gpios = <0x0b 0x08 0x00>; + resets = <&prci 0x04>; + status = "okay"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00 0x80000000 0x04 0x00>; + }; + + pwmleds { + compatible = "pwm-leds"; + + green-d12 { + label = "green:d12"; + pwms = <0x0d 0x00 0x773594 0x01>; + active-low = <0x01>; + max-brightness = <0xff>; + linux,default-trigger = "none"; + }; + + green-d2 { + label = "green:d2"; + pwms = <0x0d 0x01 0x773594 0x01>; + active-low = <0x01>; + max-brightness = <0xff>; + linux,default-trigger = "none"; + }; + + red-d2 { + label = "red:d2"; + pwms = <0x0d 0x02 0x773594 0x01>; + active-low = <0x01>; + max-brightness = <0xff>; + linux,default-trigger = "none"; + }; + + blue-d2 { + label = "blue:d2"; + pwms = <0x0d 0x03 0x773594 0x01>; + active-low = <0x01>; + max-brightness = <0xff>; + linux,default-trigger = "none"; + }; + }; + + clk_hfclk: hfclk { + #clock-cells = <0x00>; + compatible = "fixed-clock"; + clock-frequency = <26000000>; + clock-output-names = "hfclk"; + }; + + clk_rtcclk: rtcclk { + #clock-cells = <0x00>; + compatible = "fixed-clock"; + clock-frequency = <1000000>; + clock-output-names = "rtcclk"; + }; + + gpio-poweroff { + compatible = "gpio-poweroff"; + gpios = <0x0b 0x02 0x01>; + }; +}; diff --git a/kernel/driver/bsp/riscv/src/plic.rs b/kernel/driver/bsp/riscv/src/plic.rs index b8921821..4be8b184 100644 --- a/kernel/driver/bsp/riscv/src/plic.rs +++ b/kernel/driver/bsp/riscv/src/plic.rs @@ -2,7 +2,8 @@ use alloc::{sync::Arc, vec::Vec}; use device_api::{ device::{Device, DeviceInitContext}, interrupt::{ - ExternalInterruptController, InterruptHandler, Irq, IrqHandle, IrqOptions, IrqVector, + ExternalInterruptController, InterruptHandler, Irq, IrqHandle, IrqOptions, IrqPriority, + IrqVector, }, }; use device_tree::{ @@ -103,6 +104,64 @@ pub struct Plic { } impl Plic { + fn ensure_init(&self) -> Result<(), Error> { + self.inner.or_try_init_with(|| { + log::info!("Initialize RISC-V PLIC"); + + let common = + unsafe { DeviceMemoryIo::::map(self.base, Default::default())? }; + + for i in 0..self.max_irq { + common.PRIORITY[i].set(0); + } + + for context in self.context_map.iter() { + let enable_offset = ENABLE_BASE + context.index * ENABLE_STRIDE; + let control_offset = CONTROL_BASE + context.index * CONTROL_STRIDE; + + log::info!( + "* HART {}: context {}, enable={:#x}, control={:#x}", + context.hart, + context.index, + enable_offset, + control_offset + ); + let enable = unsafe { + DeviceMemoryIo::::map( + self.base.add(enable_offset), + Default::default(), + )? + }; + let control = unsafe { + DeviceMemoryIo::::map( + self.base.add(control_offset), + Default::default(), + )? + }; + + for i in 0..self.max_irq.div_ceil(32) { + enable.ENABLE[i].set(0); + } + control.THRESHOLD.set(0); + + context.context.init(Context { + enable: IrqSafeRwLock::new(enable), + control: IrqSafeRwLock::new(control), + table: FixedInterruptTable::new(MAX_IRQS), // table: IrqSafeRwLock::new(FixedInterruptTable::new()), + }); + } + + // self.inner.init(Inner { + // common: IrqSafeRwLock::new(common), + // }); + + Ok(Inner { + common: IrqSafeRwLock::new(common), + }) + })?; + Ok(()) + } + fn hart_context(&self, hart: u32) -> Option<&HartContext> { self.context_map.iter().find(|c| c.hart == hart) } @@ -153,11 +212,20 @@ impl ExternalInterruptController for Plic { fn register_irq( &self, irq: Irq, - _options: IrqOptions, + options: IrqOptions, handler: Arc, ) -> Result<(), Error> { + self.ensure_init()?; let bsp_hart_id = boot_hart_id() as u32; let irq = self.validate_irq(irq)?; + let prioval = match options.priority { + IrqPriority::Low => 3, + IrqPriority::Normal => 5, + IrqPriority::High => 7, + }; + let inner = self.inner.get(); + let common = inner.common.write(); + common.PRIORITY[irq as usize - 1].set(prioval); let context = self .hart_context(bsp_hart_id) .ok_or(Error::InvalidArgument) @@ -186,68 +254,24 @@ impl ExternalInterruptController for Plic { let control = context.control.write(); // let table = context.table.read(); - loop { - let irq = control.CLAIM.get(); - if irq == 0 { - break; - } - let vector = IrqVector::Irq(Irq::External(irq)); - - if !context.table.handle_irq_line(irq as usize, vector) { - log::warn!("plic: no handler for IRQ #{irq}"); - } - - // Done servicing - control.CLAIM.set(irq); + let irq = control.CLAIM.get(); + if irq == 0 { + return; } + let vector = IrqVector::Irq(Irq::External(irq)); + + if !context.table.handle_irq_line(irq as usize, vector) { + log::warn!("plic: no handler for IRQ #{irq}"); + } + + // Done servicing + control.CLAIM.set(irq); } } impl Device for Plic { unsafe fn init(self: Arc, _cx: DeviceInitContext) -> Result<(), Error> { - log::info!("Initialize RISC-V PLIC"); - - let common = DeviceMemoryIo::::map(self.base, Default::default())?; - - for i in 0..self.max_irq { - common.PRIORITY[i].set(3); - } - - for context in self.context_map.iter() { - let enable_offset = ENABLE_BASE + context.index * ENABLE_STRIDE; - let control_offset = CONTROL_BASE + context.index * CONTROL_STRIDE; - - log::info!( - "* HART {}: context {}, enable={:#x}, control={:#x}", - context.hart, - context.index, - enable_offset, - control_offset - ); - let enable = DeviceMemoryIo::::map( - self.base.add(enable_offset), - Default::default(), - )?; - let control = DeviceMemoryIo::::map( - self.base.add(control_offset), - Default::default(), - )?; - - for i in 0..self.max_irq.div_ceil(32) { - enable.ENABLE[i].set(0); - } - control.THRESHOLD.set(0); - - context.context.init(Context { - enable: IrqSafeRwLock::new(enable), - control: IrqSafeRwLock::new(control), - table: FixedInterruptTable::new(MAX_IRQS), // table: IrqSafeRwLock::new(FixedInterruptTable::new()), - }); - } - - self.inner.init(Inner { - common: IrqSafeRwLock::new(common), - }); + self.ensure_init()?; register_external_interrupt_controller(self); @@ -301,6 +325,7 @@ device_tree_driver! { ) else { continue; }; + log::info!("Context #{context}: mode={mode:?}, hart={hart_id}"); if mode != ContextMode::ExternalS { continue; } diff --git a/kernel/driver/bsp/sifive/src/clock.rs b/kernel/driver/bsp/sifive/src/clock_fu540.rs similarity index 100% rename from kernel/driver/bsp/sifive/src/clock.rs rename to kernel/driver/bsp/sifive/src/clock_fu540.rs diff --git a/kernel/driver/bsp/sifive/src/clock_fu740.rs b/kernel/driver/bsp/sifive/src/clock_fu740.rs new file mode 100644 index 00000000..efce2f4b --- /dev/null +++ b/kernel/driver/bsp/sifive/src/clock_fu740.rs @@ -0,0 +1,202 @@ +use alloc::sync::Arc; +use device_api::{ + clock::{ClockController, ClockHandle, Hertz}, + device::Device, +}; +use device_tree::{ + DeviceTreePropertyRead, TProp, + driver::{DeviceTreeClockController, Node, ProbeContext, device_tree_driver}, +}; +use libk::error::Error; +use libk_mm::device::DeviceMemoryIo; +use libk_util::sync::IrqSafeSpinlock; +use tock_registers::{ + interfaces::Readable, + register_bitfields, register_structs, + registers::{ReadOnly, ReadWrite}, +}; + +// const CLK_COREPLL: u32 = 0; +// const CLK_DDRPLL: u32 = 1; +// const CLK_GEMGXLPLL: u32 = 2; +// const CLK_DVFSCOREPLL: u32 = 3; +// const CLK_HFPCLKPLL: u32 = 4; +// const CLK_CLTXPLL: u32 = 5; +// const CLK_TLCLK: u32 = 6; +const CLK_PCLK: u32 = 7; +// const CLK_PCIE_AUX: u32 = 8; + +#[derive(Debug)] +struct WrpllData { + divr: u32, + divf: u32, + divq: u32, + int_feedback: bool, +} + +register_bitfields! { + u32, + PllCfg [ + PLLR OFFSET(0) NUMBITS(6) [], + PLLF OFFSET(6) NUMBITS(9) [], + PLLQ OFFSET(15) NUMBITS(3) [], + PLLBYPASS OFFSET(24) NUMBITS(1) [], + PLLFSEBYPASS OFFSET(25) NUMBITS(1) [], + PLLLOCK OFFSET(31) NUMBITS(1) [], + ] +} + +impl WrpllData { + fn fbdiv(&self) -> u32 { + if self.int_feedback { 2 } else { 1 } + } + + fn output_rate(&self, input_rate: Hertz) -> Hertz { + let fbdiv = self.fbdiv(); + let n = input_rate * fbdiv * (self.divf + 1); + let n = n / (self.divr + 1); + n >> self.divq + } +} + +register_structs! { + Regs { + (0x00 => hfxosccfg: ReadWrite), + (0x04 => core_pllcfg: ReadWrite), + (0x08 => core_plloutdiv: ReadWrite), + (0x0C => ddr_pllcfg: ReadWrite), + (0x10 => ddr_plloutdiv: ReadWrite), + (0x14 => _0), + (0x1C => gemgxl_pllcfg: ReadWrite), + (0x20 => gemgxl_plloutdiv: ReadWrite), + (0x24 => core_clk_sel_reg: ReadWrite), + (0x28 => devices_reset_n: ReadWrite), + (0x2C => clk_mux_status: ReadOnly), + (0x30 => _1), + (0x38 => dvfs_core_pllcfg: ReadWrite), + (0x3C => dvfs_core_plloutdiv: ReadWrite), + (0x40 => corepllsel: ReadWrite), + (0x44 => _2), + (0x50 => hfpclk_pllcfg: ReadWrite), + (0x54 => hfpclk_plloutdiv: ReadWrite), + (0x58 => hfpclkpllsel: ReadWrite), + (0x5C => hfpclk_div_reg: ReadWrite), + (0x60 => _3), + (0xE0 => prci_plls: ReadOnly), + (0xE4 => _4), + (0x100 => @END), + } +} + +struct Prci { + clk_hfclk: ClockHandle, + clk_rtcclk: ClockHandle, + regs: IrqSafeSpinlock>, +} + +impl Regs { + fn read_hfpclk_pll(&self) -> WrpllData { + let reg = self.hfpclk_pllcfg.extract(); + let divr = reg.read(PllCfg::PLLR); + let divq = reg.read(PllCfg::PLLQ); + let divf = reg.read(PllCfg::PLLF); + WrpllData { + divq, + divr, + divf, + int_feedback: true, + } + } +} + +impl Device for Prci { + fn display_name(&self) -> &str { + "sifive,fu740-c000-prci" + } +} + +impl ClockController for Prci { + fn clock_rate(&self, clock: Option) -> Result { + // hart frequency: coreclk, supplied either by corepll or dvfscorepll, selected by + // corepllsel + // hfpclkpll: clock for SPI, UART, GPIO, I2C, PWM + // + let _ = &self.clk_rtcclk; + let regs = self.regs.lock(); + match clock { + Some(CLK_PCLK) => { + // PCLK calculation: + // pclk <- X / hfpclkdiv + // case [hfpclkpllsel]: + // 1: X <- (hfclk) + // 0: X <- hfpclkpllcfg/out & hfpclkpll + // hfpclkdiv <- [hfpclk_div_reg] + 2 + + let hfpclkpllsel = regs.hfpclkpllsel.get() & 1 != 0; + let hfpclk_div_reg = regs.hfpclk_div_reg.get() + 2; + let x = match hfpclkpllsel { + true => self.clk_hfclk.rate()?, + false => { + let pclk_pll = regs.read_hfpclk_pll(); + pclk_pll.output_rate(self.clk_hfclk.rate()?) + } + }; + Ok(x / hfpclk_div_reg) + } + Some(_) => { + todo!(); + } + None => { + todo!(); + } + } + } + + fn set_clock_rate(&self, _clock: Option, _rate: Hertz) -> Result { + Err(Error::NotImplemented) + } + + fn enable_clock(&self, _clock: Option) -> Result<(), Error> { + Ok(()) + } + + fn disable_clock(&self, _clock: Option) -> Result<(), Error> { + Err(Error::NotImplemented) + } +} + +impl DeviceTreeClockController for Prci { + fn map_clock(self: Arc, property: &TProp, offset: usize) -> Option<(ClockHandle, usize)> { + let clock = property.read_cell(offset, 1)? as u32; + Some(( + ClockHandle { + parent: self.clone(), + clock: Some(clock), + }, + 1, + )) + } +} + +device_tree_driver! { + compatible: ["sifive,fu740-c000-prci"], + driver: { + fn probe(&self, node: &Arc, context: &mut ProbeContext) -> Option> { + let base = node.map_base(context, 0)?; + let clk_hfclk = node.clock(0)?; + let clk_rtcclk = node.clock(1)?; + + let regs = unsafe { DeviceMemoryIo::map(base, Default::default()) }.ok()?; + + let prci = Arc::new(Prci { + regs: IrqSafeSpinlock::new(regs), + clk_hfclk, + clk_rtcclk + }); + + node.make_clock_controller(prci.clone()); + + Some(prci) + } + } +} diff --git a/kernel/driver/bsp/sifive/src/lib.rs b/kernel/driver/bsp/sifive/src/lib.rs index b8f29b77..965c63d1 100644 --- a/kernel/driver/bsp/sifive/src/lib.rs +++ b/kernel/driver/bsp/sifive/src/lib.rs @@ -2,6 +2,7 @@ extern crate alloc; -mod clock; +mod clock_fu540; +mod clock_fu740; mod ethernet; mod uart; diff --git a/kernel/driver/bsp/sifive/src/uart.rs b/kernel/driver/bsp/sifive/src/uart.rs index 702a2614..24d5025f 100644 --- a/kernel/driver/bsp/sifive/src/uart.rs +++ b/kernel/driver/bsp/sifive/src/uart.rs @@ -1,8 +1,10 @@ +use core::sync::atomic::{AtomicBool, Ordering}; + use alloc::sync::Arc; use device_api::{ clock::{ClockHandle, Hertz}, device::{Device, DeviceInitContext}, - interrupt::{InterruptHandler, IrqHandle, IrqVector}, + interrupt::{InterruptHandler, IrqHandle, IrqPriority, IrqVector}, }; use device_tree::driver::{Node, ProbeContext, device_tree_driver}; use libk::{ @@ -16,9 +18,12 @@ use libk_util::{OneTimeInit, sync::IrqSafeSpinlock}; use tock_registers::{ interfaces::{Readable, Writeable}, register_bitfields, register_structs, - registers::{ReadOnly, ReadWrite, WriteOnly}, + registers::{ReadOnly, ReadWrite}, +}; +use yggdrasil_abi::{ + io::{TerminalOptions, TerminalOutputOptions}, + process::ProcessId, }; -use yggdrasil_abi::io::{TerminalOptions, TerminalOutputOptions}; register_bitfields! { u32, @@ -42,7 +47,7 @@ register_bitfields! { register_structs! { Regs { - (0x00 => txdata: WriteOnly), + (0x00 => txdata: ReadWrite), (0x04 => rxdata: ReadOnly), (0x08 => txctrl: ReadWrite), (0x0C => rxctrl: ReadWrite), @@ -57,6 +62,7 @@ register_structs! { struct Inner { clock: ClockHandle, regs: IrqSafeSpinlock>, + active: AtomicBool, } struct Uart { @@ -69,6 +75,7 @@ struct Uart { impl Regs { fn set_baud_rate(&self, input_clk: Hertz, baud: u32) -> Result<(), Error> { + // Check: given f_in=130MHz, baud=115200 should give div = 0x468 let div = Hertz::divider(input_clk, Hertz::from(baud)).ok_or(Error::InvalidArgument)?; if div >= (1 << 20) || div == 0 { return Err(Error::InvalidArgument); @@ -84,9 +91,25 @@ impl Regs { (input_clk / div).0 as u32 } + #[inline] + fn is_txfifo_full(&self) -> bool { + self.txdata.get() & (1 << 31) != 0 + } + + fn read(&self) -> Option { + let val = self.rxdata.get(); + if val & (1 << 31) == 0 { + Some(val as u8) + } else { + None + } + } + fn write(&self, byte: u8) { - while !self.ip.matches_all(interrupt::txwm::SET) { - core::hint::spin_loop(); + while self.is_txfifo_full() { + for _ in 0..10000 { + core::hint::spin_loop(); + } } self.txdata.set(byte as u32); } @@ -98,6 +121,7 @@ impl Device for Uart { self.clock.enable()?; let input_clk = self.clock.rate()?; + log::info!("input_clk = {input_clk}"); { let _guard = debug::MuteGuard::acquire(); @@ -106,13 +130,18 @@ impl Device for Uart { regs.rxctrl.write(rxctrl::rxen::CLEAR); regs.set_baud_rate(input_clk, 115200)?; regs.txctrl.write(txctrl::txen::SET + txctrl::txcnt.val(3)); - regs.rxctrl.write(rxctrl::rxen::SET + rxctrl::rxcnt.val(0)); + } + + // Drain Rx FIFO + while regs.read().is_some() { + core::hint::spin_loop(); } let input = TerminalInput::with_capacity(64)?; let output = Inner { regs: IrqSafeSpinlock::new(regs), clock: self.clock.clone(), + active: AtomicBool::new(false), }; let terminal = self.inner.init(Arc::new(Terminal::from_parts( @@ -130,10 +159,9 @@ impl Device for Uart { } unsafe fn init_irq(self: Arc) -> Result<(), Error> { - self.irq.register(self.clone())?; + self.irq + .register_with_priority(IrqPriority::Low, self.clone())?; self.irq.enable()?; - let regs = self.inner.get().output().regs.lock(); - regs.ie.write(interrupt::rxwm::SET); Ok(()) } @@ -145,15 +173,27 @@ impl Device for Uart { impl InterruptHandler for Uart { fn handle_irq(self: Arc, _vector: IrqVector) -> bool { let terminal = self.inner.get(); - let byte = { - let regs = terminal.output().regs.lock(); - if regs.ip.matches_all(interrupt::rxwm::SET) { - regs.rxdata.get() as u8 - } else { - return false; + let regs = terminal.output().regs.lock(); + let ip = regs.ip.extract(); + if ip.get() == 0 { + return false; + } + + let mut count = 0; + let mut bytes = [0; 32]; + // if ip.matches_all(interrupt::rxwm::SET) { + while let Some(byte) = regs.read() { + bytes[count] = byte; + count += 1; + } + // } + drop(regs); + for &byte in &bytes[..count] { + if byte != 0 { + terminal.write_to_input(byte); } - }; - terminal.write_to_input(byte); + } + true } } @@ -172,6 +212,20 @@ impl DebugSink for Uart { } impl TerminalOutput for Inner { + fn open(&self, _pid: ProcessId) -> Result<(), Error> { + if !self.active.swap(true, Ordering::Acquire) { + log::info!("sifive-uart: start"); + let regs = self.regs.lock(); + regs.rxctrl.write(rxctrl::rxen::SET + rxctrl::rxcnt.val(0)); + // Drain Rx FIFO + while regs.read().is_some() { + core::hint::spin_loop(); + } + regs.ie.write(interrupt::rxwm::SET); + } + Ok(()) + } + fn write(&self, byte: u8, options: &TerminalOutputOptions) -> Result<(), Error> { let regs = self.regs.lock(); if byte == b'\n' && options.contains(TerminalOutputOptions::NL_TO_CRNL) { diff --git a/kernel/lib/device-api/src/clock/freq.rs b/kernel/lib/device-api/src/clock/freq.rs index a327293c..9a6cbfe8 100644 --- a/kernel/lib/device-api/src/clock/freq.rs +++ b/kernel/lib/device-api/src/clock/freq.rs @@ -1,6 +1,6 @@ use core::{ fmt, - ops::{Div, Mul}, + ops::{Div, Mul, Shr}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -48,6 +48,14 @@ impl From for Hertz { } } +impl Shr for Hertz { + type Output = Hertz; + + fn shr(self, rhs: u32) -> Self::Output { + Self(self.0 >> rhs) + } +} + impl Mul for Hertz { type Output = Hertz; diff --git a/kernel/lib/device-api/src/interrupt.rs b/kernel/lib/device-api/src/interrupt.rs index 24698e65..0057835b 100644 --- a/kernel/lib/device-api/src/interrupt.rs +++ b/kernel/lib/device-api/src/interrupt.rs @@ -34,10 +34,19 @@ pub enum IrqTrigger { Level, } +#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)] +pub enum IrqPriority { + Low, + #[default] + Normal, + High, +} + #[derive(Default, Clone, Copy, Debug, PartialEq, Eq)] pub struct IrqOptions { pub level: IrqLevel, pub trigger: IrqTrigger, + pub priority: IrqPriority, } #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -152,6 +161,18 @@ impl IrqHandle { self.intc.register_irq(self.irq, self.options, handler) } + pub fn register_with_priority( + &self, + priority: IrqPriority, + handler: Arc, + ) -> Result<(), Error> { + let options = IrqOptions { + priority, + ..self.options + }; + self.intc.register_irq(self.irq, options, handler) + } + pub fn enable(&self) -> Result<(), Error> { self.intc.enable_irq(self.irq) } diff --git a/kernel/libk/libk-util/src/lru_hash_table.rs b/kernel/libk/libk-util/src/lru_hash_table.rs index 12391d73..8a8eaffe 100644 --- a/kernel/libk/libk-util/src/lru_hash_table.rs +++ b/kernel/libk/libk-util/src/lru_hash_table.rs @@ -54,11 +54,7 @@ impl LruCacheBucket { pub fn entry_mut(&mut self, key: &K) -> EntryMut<'_, K, V> { let mut cursor = self.data.cursor_front_mut(); - loop { - let Some(node) = cursor.current() else { - break; - }; - + while let Some(node) = cursor.current() { // If entry found corresponding to the key, remove it and reinsert at the front if &node.0 == key { // Safety: just checked it's not None above, so safe diff --git a/kernel/libk/src/config/general.rs b/kernel/libk/src/config/general.rs index bf166741..9e3ce6a4 100644 --- a/kernel/libk/src/config/general.rs +++ b/kernel/libk/src/config/general.rs @@ -26,7 +26,7 @@ pub struct DeviceTreeOptions { impl Default for DebugOptions { fn default() -> Self { Self { - serial_level: LogLevel::Info, + serial_level: LogLevel::Debug, display_level: LogLevel::Info, disable_program_trace: false, } diff --git a/kernel/src/init.rs b/kernel/src/init.rs index df6f92c6..c96c0c19 100644 --- a/kernel/src/init.rs +++ b/kernel/src/init.rs @@ -102,6 +102,8 @@ pub fn kinit() -> Result<(), Error> { load_kernel_symbol_table(&mut ioctx, "/kernel.sym")?; } + log::info!("Starting init"); + { let group_id = Process::create_group(); let options = LoadOptions { diff --git a/userspace/etc/rc.d/40-set-loglevel b/userspace/etc/rc.d/40-set-loglevel new file mode 100755 index 00000000..6da553df --- /dev/null +++ b/userspace/etc/rc.d/40-set-loglevel @@ -0,0 +1,3 @@ +#!/bin/sh + +/bin/echo info >/sys/debug/1/level diff --git a/userspace/tools/init/src/rc.rs b/userspace/tools/init/src/rc.rs index e3a35626..8a90a691 100644 --- a/userspace/tools/init/src/rc.rs +++ b/userspace/tools/init/src/rc.rs @@ -85,6 +85,7 @@ fn usage(_cmd: &str) { } fn main() -> ExitCode { + logsink::setup_logging(false); let args: Vec<_> = env::args().collect(); if args.len() != 2 { eprintln!("Incorrect rc usage, expected 2 args, got {}", args.len()); diff --git a/userspace/tools/shell/src/command/eval.rs b/userspace/tools/shell/src/command/eval.rs index e16cbd89..94e3b408 100644 --- a/userspace/tools/shell/src/command/eval.rs +++ b/userspace/tools/shell/src/command/eval.rs @@ -1,7 +1,13 @@ -use std::{io::BufReader, marker::PhantomData, process::ExitCode}; +use std::{ + fs::{File, OpenOptions}, + io::BufReader, + marker::PhantomData, + process::ExitCode, +}; use crate::{ builtin::{self, Envs}, + command::{ExpandedInputRedirect, ExpandedOutputRedirect}, error::Error, exec::{Execution, InheritStdout, Input, Outcome, Output, exec_pipeline, wait_for_pipeline}, syntax::parse::{BinaryOperator, ConditionalExpression, Expression}, @@ -13,12 +19,35 @@ pub fn evaluate_pipeline( pipeline: &ExpandedPipeline, env: &mut Environment, ) -> Result<(Outcome, Option), Error> { + assert!(!pipeline.elements.is_empty()); + let mut executions = vec![]; let mut stdins = vec![]; let mut stdouts = vec![]; - let pipeline_stdin = Input::Inherit; - let pipeline_stdout = Output::::Inherit(PhantomData); + let first = pipeline.elements.first().unwrap(); + let last = pipeline.elements.last().unwrap(); + + let pipeline_stdin = match first.stdin.as_ref() { + Some(ExpandedInputRedirect::File(path)) => { + Input::File(File::open(path).map(BufReader::new)?) + } + None => Input::Inherit, + }; + let pipeline_stdout = match last.stdout.as_ref() { + Some(ExpandedOutputRedirect::File(path, append)) => { + let mut opts = OpenOptions::new(); + opts.create(true).write(true); + if *append { + opts.append(true); + } else { + opts.truncate(true); + } + let file = opts.open(path)?; + Output::File(file) + } + None => Output::::Inherit(PhantomData), + }; stdins.push(pipeline_stdin); for _ in 1..pipeline.elements.len() { diff --git a/userspace/tools/shell/src/command/mod.rs b/userspace/tools/shell/src/command/mod.rs index a073312e..5e369769 100644 --- a/userspace/tools/shell/src/command/mod.rs +++ b/userspace/tools/shell/src/command/mod.rs @@ -1,19 +1,39 @@ +use std::path::PathBuf; + use env::Environment; -use crate::syntax::parse::{PipelineElement, PipelineExpression}; +use crate::syntax::{ + lex::{InputRedirect, OutputRedirectTarget, Redirect, WordToken}, + parse::{PipelineElement, PipelineExpression}, +}; pub mod env; pub mod eval; +pub enum ExpandedInputRedirect { + File(PathBuf), +} + +pub enum ExpandedOutputRedirect { + File(PathBuf, bool), +} + pub struct ExpandedPipelineElement { pub words: Vec, pub envs: Vec<(String, String)>, + pub stdin: Option, + pub stdout: Option, + pub stderr: Option, } pub struct ExpandedPipeline { pub elements: Vec, } +fn expand_path(word: &WordToken, env: &Environment) -> PathBuf { + env.expand(word).join(" ").into() +} + impl ExpandedPipelineElement { pub fn from_syntax(env: &Environment, element: &PipelineElement) -> Self { // TODO redirects @@ -24,6 +44,36 @@ impl ExpandedPipelineElement { .collect(); let mut envs = vec![]; + let mut stdin = None; + let mut stdout = None; + let mut stderr = None; + + for redirect in &element.redirects { + match redirect { + Redirect::Input(input) => match input { + InputRedirect::Heredoc(_) => todo!("Heredoc input redirects"), + InputRedirect::Filename(filename) => { + let path = expand_path(filename, env); + stdin = Some(ExpandedInputRedirect::File(path)); + } + }, + Redirect::Output(output) => { + let source = match output.source { + Some("1") | Some("out") | None => &mut stdout, + Some("2") | Some("err") => &mut stderr, + Some(p) => todo!("Unhandled output redirect source: {p:?}"), + }; + let target = match &output.target { + OutputRedirectTarget::Filename(filename) => { + ExpandedOutputRedirect::File(expand_path(filename, env), output.append) + } + OutputRedirectTarget::Descriptor(_) => todo!("Output redirect to FD"), + }; + *source = Some(target); + } + } + } + words.retain(|word| { if let Some((key, value)) = word.split_once('=') && !key.ends_with(' ') @@ -36,7 +86,13 @@ impl ExpandedPipelineElement { } }); - Self { words, envs } + Self { + words, + envs, + stdin, + stdout, + stderr, + } } } diff --git a/xtask/src/build/cargo.rs b/xtask/src/build/cargo.rs index e17949ab..4623e243 100644 --- a/xtask/src/build/cargo.rs +++ b/xtask/src/build/cargo.rs @@ -92,6 +92,7 @@ impl<'e> CargoBuilder<'e> { command .arg(arg) .arg("-Zbuild-std=core,alloc") + .arg("-Zjson-target-spec") .arg(&format!("-Zbuild-std-features={build_std_features}")) .arg(&format!("--target={target}"));