diff --git a/Cargo.lock b/Cargo.lock index c223325a..76e53d81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -532,12 +532,6 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "elf" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" - [[package]] name = "encode_unicode" version = "1.0.0" @@ -741,18 +735,6 @@ dependencies = [ "pin-utils", ] -[[package]] -name = "gentables" -version = "0.1.0" -dependencies = [ - "bitflags 2.8.0", - "bytemuck", - "clap", - "elf 0.7.4", - "memtables", - "thiserror", -] - [[package]] name = "getrandom" version = "0.2.15" @@ -1254,7 +1236,7 @@ dependencies = [ "cfg-if", "crossbeam-queue", "device-api", - "elf 0.7.2", + "elf", "futures-util", "kernel-arch", "libc", @@ -2958,7 +2940,7 @@ dependencies = [ "device-api", "device-api-macros", "device-tree", - "elf 0.7.2", + "elf", "ext2", "futures-util", "git-version", diff --git a/Cargo.toml b/Cargo.toml index 18bb9413..fcc9a34c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,6 @@ exclude = [ ] members = [ "xtask", - "kernel/tools/gentables", "kernel", "lib/abi", "lib/libyalloc", diff --git a/etc/aarch64-unknown-none.json b/etc/aarch64-unknown-none.json index cea03353..059955ad 100644 --- a/etc/aarch64-unknown-none.json +++ b/etc/aarch64-unknown-none.json @@ -13,6 +13,7 @@ "panic-strategy": "abort", "dynamic-linking": true, "relocation-model": "pic", + "position-independent-executables": true, "eh-frame-header": false, "linker": "rust-lld", diff --git a/etc/dtb/aarch64-qemu-virt.dtb b/etc/dtb/aarch64-qemu-virt.dtb new file mode 100644 index 00000000..e673688a Binary files /dev/null and b/etc/dtb/aarch64-qemu-virt.dtb differ diff --git a/etc/dtb/aarch64-qemu-virt.dts b/etc/dtb/aarch64-qemu-virt.dts new file mode 100644 index 00000000..a1575958 --- /dev/null +++ b/etc/dtb/aarch64-qemu-virt.dts @@ -0,0 +1,433 @@ +/dts-v1/; + +/ { + interrupt-parent = <0x8005>; + dma-coherent; + model = "linux,dummy-virt"; + #size-cells = <0x02>; + #address-cells = <0x02>; + compatible = "linux,dummy-virt"; + + psci { + migrate = <0xc4000005>; + cpu_on = <0xc4000003>; + cpu_off = <0x84000002>; + cpu_suspend = <0xc4000001>; + method = "smc"; + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + }; + + memory@40000000 { + reg = <0x00 0x40000000 0x00 0x20000000>; + device_type = "memory"; + }; + + platform-bus@c000000 { + interrupt-parent = <0x8005>; + ranges = <0x00 0x00 0xc000000 0x2000000>; + #address-cells = <0x01>; + #size-cells = <0x01>; + compatible = "qemu,platform", "simple-bus"; + }; + + fw-cfg@9020000 { + dma-coherent; + reg = <0x00 0x9020000 0x00 0x18>; + compatible = "qemu,fw-cfg-mmio"; + }; + + virtio_mmio@a000000 { + dma-coherent; + interrupts = <0x00 0x10 0x01>; + reg = <0x00 0xa000000 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000200 { + dma-coherent; + interrupts = <0x00 0x11 0x01>; + reg = <0x00 0xa000200 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000400 { + dma-coherent; + interrupts = <0x00 0x12 0x01>; + reg = <0x00 0xa000400 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000600 { + dma-coherent; + interrupts = <0x00 0x13 0x01>; + reg = <0x00 0xa000600 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000800 { + dma-coherent; + interrupts = <0x00 0x14 0x01>; + reg = <0x00 0xa000800 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000a00 { + dma-coherent; + interrupts = <0x00 0x15 0x01>; + reg = <0x00 0xa000a00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000c00 { + dma-coherent; + interrupts = <0x00 0x16 0x01>; + reg = <0x00 0xa000c00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a000e00 { + dma-coherent; + interrupts = <0x00 0x17 0x01>; + reg = <0x00 0xa000e00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001000 { + dma-coherent; + interrupts = <0x00 0x18 0x01>; + reg = <0x00 0xa001000 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001200 { + dma-coherent; + interrupts = <0x00 0x19 0x01>; + reg = <0x00 0xa001200 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001400 { + dma-coherent; + interrupts = <0x00 0x1a 0x01>; + reg = <0x00 0xa001400 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001600 { + dma-coherent; + interrupts = <0x00 0x1b 0x01>; + reg = <0x00 0xa001600 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001800 { + dma-coherent; + interrupts = <0x00 0x1c 0x01>; + reg = <0x00 0xa001800 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001a00 { + dma-coherent; + interrupts = <0x00 0x1d 0x01>; + reg = <0x00 0xa001a00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001c00 { + dma-coherent; + interrupts = <0x00 0x1e 0x01>; + reg = <0x00 0xa001c00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a001e00 { + dma-coherent; + interrupts = <0x00 0x1f 0x01>; + reg = <0x00 0xa001e00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002000 { + dma-coherent; + interrupts = <0x00 0x20 0x01>; + reg = <0x00 0xa002000 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002200 { + dma-coherent; + interrupts = <0x00 0x21 0x01>; + reg = <0x00 0xa002200 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002400 { + dma-coherent; + interrupts = <0x00 0x22 0x01>; + reg = <0x00 0xa002400 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002600 { + dma-coherent; + interrupts = <0x00 0x23 0x01>; + reg = <0x00 0xa002600 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002800 { + dma-coherent; + interrupts = <0x00 0x24 0x01>; + reg = <0x00 0xa002800 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002a00 { + dma-coherent; + interrupts = <0x00 0x25 0x01>; + reg = <0x00 0xa002a00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002c00 { + dma-coherent; + interrupts = <0x00 0x26 0x01>; + reg = <0x00 0xa002c00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a002e00 { + dma-coherent; + interrupts = <0x00 0x27 0x01>; + reg = <0x00 0xa002e00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003000 { + dma-coherent; + interrupts = <0x00 0x28 0x01>; + reg = <0x00 0xa003000 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003200 { + dma-coherent; + interrupts = <0x00 0x29 0x01>; + reg = <0x00 0xa003200 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003400 { + dma-coherent; + interrupts = <0x00 0x2a 0x01>; + reg = <0x00 0xa003400 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003600 { + dma-coherent; + interrupts = <0x00 0x2b 0x01>; + reg = <0x00 0xa003600 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003800 { + dma-coherent; + interrupts = <0x00 0x2c 0x01>; + reg = <0x00 0xa003800 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003a00 { + dma-coherent; + interrupts = <0x00 0x2d 0x01>; + reg = <0x00 0xa003a00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003c00 { + dma-coherent; + interrupts = <0x00 0x2e 0x01>; + reg = <0x00 0xa003c00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + virtio_mmio@a003e00 { + dma-coherent; + interrupts = <0x00 0x2f 0x01>; + reg = <0x00 0xa003e00 0x00 0x200>; + compatible = "virtio,mmio"; + }; + + gpio-keys { + compatible = "gpio-keys"; + + poweroff { + gpios = <0x8007 0x03 0x00>; + linux,code = <0x74>; + label = "GPIO Key Poweroff"; + }; + }; + + pl061@9030000 { + phandle = <0x8007>; + clock-names = "apb_pclk"; + clocks = <0x8000>; + interrupts = <0x00 0x07 0x04>; + gpio-controller; + #gpio-cells = <0x02>; + compatible = "arm,pl061", "arm,primecell"; + reg = <0x00 0x9030000 0x00 0x1000>; + }; + + pcie@10000000 { + interrupt-map-mask = <0x1800 0x00 0x00 0x07>; + interrupt-map = <0x00 0x00 0x00 0x01 0x8005 0x00 0x00 0x00 0x03 0x04 0x00 0x00 0x00 0x02 0x8005 0x00 0x00 0x00 0x04 0x04 0x00 0x00 0x00 0x03 0x8005 0x00 0x00 0x00 0x05 0x04 0x00 0x00 0x00 0x04 0x8005 0x00 0x00 0x00 0x06 0x04 0x800 0x00 0x00 0x01 0x8005 0x00 0x00 0x00 0x04 0x04 0x800 0x00 0x00 0x02 0x8005 0x00 0x00 0x00 0x05 0x04 0x800 0x00 0x00 0x03 0x8005 0x00 0x00 0x00 0x06 0x04 0x800 0x00 0x00 0x04 0x8005 0x00 0x00 0x00 0x03 0x04 0x1000 0x00 0x00 0x01 0x8005 0x00 0x00 0x00 0x05 0x04 0x1000 0x00 0x00 0x02 0x8005 0x00 0x00 0x00 0x06 0x04 0x1000 0x00 0x00 0x03 0x8005 0x00 0x00 0x00 0x03 0x04 0x1000 0x00 0x00 0x04 0x8005 0x00 0x00 0x00 0x04 0x04 0x1800 0x00 0x00 0x01 0x8005 0x00 0x00 0x00 0x06 0x04 0x1800 0x00 0x00 0x02 0x8005 0x00 0x00 0x00 0x03 0x04 0x1800 0x00 0x00 0x03 0x8005 0x00 0x00 0x00 0x04 0x04 0x1800 0x00 0x00 0x04 0x8005 0x00 0x00 0x00 0x05 0x04>; + #interrupt-cells = <0x01>; + ranges = <0x1000000 0x00 0x00 0x00 0x3eff0000 0x00 0x10000 0x2000000 0x00 0x10000000 0x00 0x10000000 0x00 0x2eff0000 0x3000000 0x80 0x00 0x80 0x00 0x80 0x00>; + reg = <0x40 0x10000000 0x00 0x10000000>; + msi-map = <0x00 0x8006 0x00 0x10000>; + dma-coherent; + bus-range = <0x00 0xff>; + linux,pci-domain = <0x00>; + #size-cells = <0x02>; + #address-cells = <0x03>; + device_type = "pci"; + compatible = "pci-host-ecam-generic"; + }; + + pl031@9010000 { + clock-names = "apb_pclk"; + clocks = <0x8000>; + interrupts = <0x00 0x02 0x04>; + reg = <0x00 0x9010000 0x00 0x1000>; + compatible = "arm,pl031", "arm,primecell"; + }; + + pl011@9000000 { + clock-names = "uartclk", "apb_pclk"; + clocks = <0x8000 0x8000>; + interrupts = <0x00 0x01 0x04>; + reg = <0x00 0x9000000 0x00 0x1000>; + compatible = "arm,pl011", "arm,primecell"; + }; + + pmu { + interrupts = <0x01 0x07 0xf04>; + compatible = "arm,armv8-pmuv3"; + }; + + intc@8000000 { + phandle = <0x8005>; + interrupts = <0x01 0x09 0x04>; + reg = <0x00 0x8000000 0x00 0x10000 0x00 0x8010000 0x00 0x10000 0x00 0x8030000 0x00 0x10000 0x00 0x8040000 0x00 0x10000>; + compatible = "arm,cortex-a15-gic"; + ranges; + #size-cells = <0x02>; + #address-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x03>; + + v2m@8020000 { + phandle = <0x8006>; + reg = <0x00 0x8020000 0x00 0x1000>; + msi-controller; + compatible = "arm,gic-v2m-frame"; + }; + }; + + flash@0 { + bank-width = <0x04>; + reg = <0x00 0x00 0x00 0x4000000 0x00 0x4000000 0x00 0x4000000>; + compatible = "cfi-flash"; + }; + + cpus { + #size-cells = <0x00>; + #address-cells = <0x01>; + + cpu-map { + + socket0 { + + cluster0 { + + core0 { + cpu = <0x8004>; + }; + + core1 { + cpu = <0x8003>; + }; + + core2 { + cpu = <0x8002>; + }; + + core3 { + cpu = <0x8001>; + }; + }; + }; + }; + + cpu@0 { + phandle = <0x8004>; + reg = <0x00>; + enable-method = "psci"; + compatible = "arm,cortex-a57"; + device_type = "cpu"; + }; + + cpu@1 { + phandle = <0x8003>; + reg = <0x01>; + enable-method = "psci"; + compatible = "arm,cortex-a57"; + device_type = "cpu"; + }; + + cpu@2 { + phandle = <0x8002>; + reg = <0x02>; + enable-method = "psci"; + compatible = "arm,cortex-a57"; + device_type = "cpu"; + }; + + cpu@3 { + phandle = <0x8001>; + reg = <0x03>; + enable-method = "psci"; + compatible = "arm,cortex-a57"; + device_type = "cpu"; + }; + }; + + timer { + interrupts = <0x01 0x0d 0xf04 0x01 0x0e 0xf04 0x01 0x0b 0xf04 0x01 0x0a 0xf04 0x01 0x0c 0xf04>; + always-on; + compatible = "arm,armv8-timer", "arm,armv7-timer"; + }; + + apb-pclk { + phandle = <0x8000>; + clock-output-names = "clk24mhz"; + clock-frequency = <0x16e3600>; + #clock-cells = <0x00>; + compatible = "fixed-clock"; + }; + + aliases { + serial0 = "/pl011@9000000"; + }; + + chosen { + linux,initrd-end = <0x00 0x49fd4600>; + linux,initrd-start = <0x00 0x48000000>; + stdout-path = "/pl011@9000000"; + rng-seed = <0xf119f64b 0xacade219 0xaefd1e87 0x5fb37f65 0xc770054a 0xd779b25f 0x1ba6d6e9 0x8121c19d>; + kaslr-seed = <0x1f500308 0xbb36e27a>; + }; +}; diff --git a/etc/dtb/bcm2711-rpi-4-b.dts b/etc/dtb/bcm2711-rpi-4-b.dts new file mode 100644 index 00000000..32b95cf1 --- /dev/null +++ b/etc/dtb/bcm2711-rpi-4-b.dts @@ -0,0 +1,2720 @@ +/dts-v1/; + +/memreserve/ 0x0000000000000000 0x0000000000001000; +/ { + compatible = "raspberrypi,4-model-b", "brcm,bcm2711"; + model = "Raspberry Pi 4 Model B"; + #address-cells = <0x02>; + #size-cells = <0x01>; + interrupt-parent = <0x01>; + + aliases { + serial0 = "/soc/serial@7e215040"; + serial1 = "/soc/serial@7e201000"; + emmc2bus = "/emmc2bus"; + ethernet0 = "/scb/ethernet@7d580000"; + pcie0 = "/scb/pcie@7d500000"; + blconfig = "/reserved-memory/nvram@0"; + blpubkey = "/reserved-memory/nvram@1"; + bluetooth = "/soc/serial@7e201000/bluetooth"; + aux = "/soc/aux@7e215000"; + sound = "/soc/sound"; + soc = "/soc"; + dma = "/soc/dma-controller@7e007000"; + watchdog = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + uart0 = "/soc/serial@7e201000"; + uart1 = "/soc/serial@7e215040"; + sdhost = "/soc/mmc@7e202000"; + mmc = "/soc/mmc@7e300000"; + mmc1 = "/soc/mmcnr@7e300000"; + mmc0 = "/emmc2bus/mmc@7e340000"; + i2s = "/soc/i2s@7e203000"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c1 = "/soc/i2c@7e804000"; + i2c10 = "/soc/i2c0mux/i2c@1"; + i2c = "/soc/i2c@7e804000"; + spi0 = "/soc/spi@7e204000"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + usb = "/soc/usb@7e980000"; + leds = "/leds"; + fb = "/soc/fb"; + thermal = "/soc/avs-monitor@7d5d2000/thermal"; + axiperf = "/soc/axiperf"; + uart2 = "/soc/serial@7e201400"; + uart3 = "/soc/serial@7e201600"; + uart4 = "/soc/serial@7e201800"; + uart5 = "/soc/serial@7e201a00"; + serial2 = "/soc/serial@7e201400"; + serial3 = "/soc/serial@7e201600"; + serial4 = "/soc/serial@7e201800"; + serial5 = "/soc/serial@7e201a00"; + mmc2 = "/soc/mmc@7e202000"; + i2c3 = "/soc/i2c@7e205600"; + i2c4 = "/soc/i2c@7e205800"; + i2c5 = "/soc/i2c@7e205a00"; + i2c6 = "/soc/i2c@7e205c00"; + i2c20 = "/soc/i2c@7ef04500"; + i2c21 = "/soc/i2c@7ef09500"; + spi3 = "/soc/spi@7e204600"; + spi4 = "/soc/spi@7e204800"; + spi5 = "/soc/spi@7e204a00"; + spi6 = "/soc/spi@7e204c00"; + phandle = <0x4f>; + }; + + chosen { + stdout-path = "serial0:115200n8"; + bootargs = "coherent_pool=1M 8250.nr_uarts=1 snd_bcm2835.enable_headphones=0 cgroup_disable=memory numa_policy=interleave"; + phandle = <0x54>; + }; + + reserved-memory { + #address-cells = <0x02>; + #size-cells = <0x01>; + ranges; + phandle = <0x5c>; + + linux,cma { + compatible = "shared-dma-pool"; + size = <0x4000000>; + reusable; + linux,cma-default; + alloc-ranges = <0x00 0x00 0x30000000>; + phandle = <0x5d>; + }; + + nvram@0 { + compatible = "raspberrypi,bootloader-config", "nvmem-rmem"; + #address-cells = <0x01>; + #size-cells = <0x01>; + reg = <0x00 0x00 0x00>; + no-map; + status = "disabled"; + phandle = <0x5e>; + }; + + nvram@1 { + compatible = "raspberrypi,bootloader-public-key", "nvmem-rmem"; + #address-cells = <0x01>; + #size-cells = <0x01>; + reg = <0x00 0x00 0x00>; + no-map; + status = "disabled"; + phandle = <0x5f>; + }; + }; + + thermal-zones { + + cpu-thermal { + polling-delay-passive = <0x00>; + polling-delay = <0x3e8>; + coefficients = <0xfffffe19 0x641b8>; + thermal-sensors = <0x02>; + phandle = <0x60>; + + trips { + phandle = <0x61>; + + cpu-crit { + temperature = <0x1adb0>; + hysteresis = <0x00>; + type = "critical"; + }; + }; + + cooling-maps { + phandle = <0x62>; + }; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges = <0x7e000000 0x00 0xfe000000 0x1800000 0x7c000000 0x00 0xfc000000 0x2000000 0x40000000 0x00 0xff800000 0x800000>; + dma-ranges = <0xc0000000 0x00 0x00 0x40000000 0x7c000000 0x00 0xfc000000 0x3800000>; + phandle = <0x63>; + + timer@7e003000 { + compatible = "brcm,bcm2835-system-timer"; + reg = <0x7e003000 0x1000>; + interrupts = <0x00 0x40 0x04 0x00 0x41 0x04 0x00 0x42 0x04 0x00 0x43 0x04>; + clock-frequency = <0xf4240>; + status = "disabled"; + phandle = <0x64>; + }; + + txp@7e004000 { + compatible = "brcm,bcm2835-txp"; + reg = <0x7e004000 0x20>; + interrupts = <0x00 0x4b 0x04>; + status = "disabled"; + phandle = <0x65>; + }; + + cprman@7e101000 { + compatible = "brcm,bcm2711-cprman"; + #clock-cells = <0x01>; + reg = <0x7e101000 0x2000>; + clocks = <0x03 0x04 0x00 0x04 0x01 0x04 0x02 0x05 0x00 0x05 0x01 0x05 0x02>; + firmware = <0x06>; + phandle = <0x08>; + }; + + mailbox@7e00b880 { + compatible = "brcm,bcm2835-mbox"; + reg = <0x7e00b880 0x40>; + interrupts = <0x00 0x21 0x04>; + #mbox-cells = <0x00>; + phandle = <0x35>; + }; + + gpio@7e200000 { + compatible = "brcm,bcm2711-gpio"; + reg = <0x7e200000 0xb4>; + interrupts = <0x00 0x71 0x04 0x00 0x72 0x04>; + gpio-controller; + #gpio-cells = <0x02>; + interrupt-controller; + #interrupt-cells = <0x02>; + gpio-ranges = <0x07 0x00 0x00 0x3a>; + gpio-line-names = "ID_SDA", "ID_SCL", "GPIO2", "GPIO3", "GPIO4", "GPIO5", "GPIO6", "GPIO7", "GPIO8", "GPIO9", "GPIO10", "GPIO11", "GPIO12", "GPIO13", "GPIO14", "GPIO15", "GPIO16", "GPIO17", "GPIO18", "GPIO19", "GPIO20", "GPIO21", "GPIO22", "GPIO23", "GPIO24", "GPIO25", "GPIO26", "GPIO27", "RGMII_MDIO", "RGMIO_MDC", "CTS0", "RTS0", "TXD0", "RXD0", "SD1_CLK", "SD1_CMD", "SD1_DATA0", "SD1_DATA1", "SD1_DATA2", "SD1_DATA3", "PWM0_MISO", "PWM1_MOSI", "STATUS_LED_G_CLK", "SPIFLASH_CE_N", "SDA0", "SCL0", "RGMII_RXCLK", "RGMII_RXCTL", "RGMII_RXD0", "RGMII_RXD1", "RGMII_RXD2", "RGMII_RXD3", "RGMII_TXCLK", "RGMII_TXCTL", "RGMII_TXD0", "RGMII_TXD1", "RGMII_TXD2", "RGMII_TXD3"; + phandle = <0x07>; + + dpi-gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x06>; + phandle = <0x66>; + }; + + emmc-gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x07>; + phandle = <0x67>; + }; + + emmc-gpio34 { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x68>; + }; + + emmc-gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x07>; + phandle = <0x13>; + }; + + gpclk0-gpio4 { + brcm,pins = <0x04>; + brcm,function = <0x04>; + phandle = <0x69>; + }; + + gpclk1-gpio5 { + brcm,pins = <0x05>; + brcm,function = <0x04>; + phandle = <0x6a>; + }; + + gpclk1-gpio42 { + brcm,pins = <0x2a>; + brcm,function = <0x04>; + phandle = <0x6b>; + }; + + gpclk1-gpio44 { + brcm,pins = <0x2c>; + brcm,function = <0x04>; + phandle = <0x6c>; + }; + + gpclk2-gpio6 { + brcm,pins = <0x06>; + brcm,function = <0x04>; + phandle = <0x6d>; + }; + + gpclk2-gpio43 { + brcm,pins = <0x2b>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x6e>; + }; + + i2c0if-gpio0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + phandle = <0x33>; + }; + + i2c0if-gpio28 { + brcm,pins = <0x1c 0x1d>; + brcm,function = <0x04>; + phandle = <0x6f>; + }; + + i2c0if-gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x05>; + phandle = <0x34>; + }; + + i2c1-gpio2 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + phandle = <0x70>; + }; + + i2c1-gpio44 { + brcm,pins = <0x2c 0x2d>; + brcm,function = <0x06>; + phandle = <0x71>; + }; + + jtag-gpio22 { + brcm,pins = <0x16 0x17 0x18 0x19 0x1a 0x1b>; + brcm,function = <0x03>; + phandle = <0x72>; + }; + + pcm-gpio18 { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x73>; + }; + + pcm-gpio28 { + brcm,pins = <0x1c 0x1d 0x1e 0x1f>; + brcm,function = <0x06>; + phandle = <0x74>; + }; + + sdhost-gpio48 { + brcm,pins = <0x30 0x31 0x32 0x33 0x34 0x35>; + brcm,function = <0x04>; + phandle = <0x75>; + }; + + spi0-gpio7 { + brcm,pins = <0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x76>; + }; + + spi0-gpio35 { + brcm,pins = <0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x04>; + phandle = <0x77>; + }; + + spi1-gpio16 { + brcm,pins = <0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x03>; + phandle = <0x78>; + }; + + spi2-gpio40 { + brcm,pins = <0x28 0x29 0x2a 0x2b 0x2c 0x2d>; + brcm,function = <0x03>; + phandle = <0x79>; + }; + + uart0-gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x04>; + phandle = <0x7a>; + }; + + uart0-ctsrts-gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x07>; + phandle = <0x7b>; + }; + + uart0-ctsrts-gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x07>; + brcm,pull = <0x02 0x00>; + phandle = <0x7c>; + }; + + uart0-gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x7d>; + }; + + uart0-gpio36 { + brcm,pins = <0x24 0x25>; + brcm,function = <0x06>; + phandle = <0x7e>; + }; + + uart0-ctsrts-gpio38 { + brcm,pins = <0x26 0x27>; + brcm,function = <0x06>; + phandle = <0x7f>; + }; + + uart1-gpio14 { + brcm,pins = <0x0e 0x0f>; + brcm,function = <0x02>; + phandle = <0x80>; + }; + + uart1-ctsrts-gpio16 { + brcm,pins = <0x10 0x11>; + brcm,function = <0x02>; + phandle = <0x81>; + }; + + uart1-gpio32 { + brcm,pins = <0x20 0x21>; + brcm,function = <0x02>; + phandle = <0x82>; + }; + + uart1-ctsrts-gpio30 { + brcm,pins = <0x1e 0x1f>; + brcm,function = <0x02>; + phandle = <0x83>; + }; + + uart1-gpio40 { + brcm,pins = <0x28 0x29>; + brcm,function = <0x02>; + phandle = <0x84>; + }; + + uart1-ctsrts-gpio42 { + brcm,pins = <0x2a 0x2b>; + brcm,function = <0x02>; + phandle = <0x85>; + }; + + gpclk0-gpio49 { + phandle = <0x86>; + + pin-gpclk { + pins = "gpio49"; + function = "alt1"; + bias-disable; + }; + }; + + gpclk1-gpio50 { + phandle = <0x87>; + + pin-gpclk { + pins = "gpio50"; + function = "alt1"; + bias-disable; + }; + }; + + gpclk2-gpio51 { + phandle = <0x88>; + + pin-gpclk { + pins = "gpio51"; + function = "alt1"; + bias-disable; + }; + }; + + i2c0if-gpio46 { + phandle = <0x89>; + + pin-sda { + function = "alt0"; + pins = "gpio46"; + bias-pull-up; + }; + + pin-scl { + function = "alt0"; + pins = "gpio47"; + bias-disable; + }; + }; + + i2c1-gpio46 { + phandle = <0x8a>; + + pin-sda { + function = "alt1"; + pins = "gpio46"; + bias-pull-up; + }; + + pin-scl { + function = "alt1"; + pins = "gpio47"; + bias-disable; + }; + }; + + i2c3-gpio2 { + phandle = <0x8b>; + + pin-sda { + function = "alt5"; + pins = "gpio2"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio3"; + bias-disable; + }; + }; + + i2c3-gpio4 { + phandle = <0x8c>; + + pin-sda { + function = "alt5"; + pins = "gpio4"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio5"; + bias-disable; + }; + }; + + i2c4-gpio6 { + phandle = <0x8d>; + + pin-sda { + function = "alt5"; + pins = "gpio6"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio7"; + bias-disable; + }; + }; + + i2c4-gpio8 { + phandle = <0x8e>; + + pin-sda { + function = "alt5"; + pins = "gpio8"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio9"; + bias-disable; + }; + }; + + i2c5-gpio10 { + phandle = <0x8f>; + + pin-sda { + function = "alt5"; + pins = "gpio10"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio11"; + bias-disable; + }; + }; + + i2c5-gpio12 { + phandle = <0x90>; + + pin-sda { + function = "alt5"; + pins = "gpio12"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio13"; + bias-disable; + }; + }; + + i2c6-gpio0 { + phandle = <0x91>; + + pin-sda { + function = "alt5"; + pins = "gpio0"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio1"; + bias-disable; + }; + }; + + i2c6-gpio22 { + phandle = <0x92>; + + pin-sda { + function = "alt5"; + pins = "gpio22"; + bias-pull-up; + }; + + pin-scl { + function = "alt5"; + pins = "gpio23"; + bias-disable; + }; + }; + + i2c-slave-gpio8 { + phandle = <0x93>; + + pins-i2c-slave { + pins = "gpio8", "gpio9", "gpio10", "gpio11"; + function = "alt3"; + }; + }; + + jtag-gpio48 { + phandle = <0x94>; + + pins-jtag { + pins = "gpio48", "gpio49", "gpio50", "gpio51", "gpio52", "gpio53"; + function = "alt4"; + }; + }; + + mii-gpio28 { + phandle = <0x95>; + + pins-mii { + pins = "gpio28", "gpio29", "gpio30", "gpio31"; + function = "alt4"; + }; + }; + + mii-gpio36 { + phandle = <0x96>; + + pins-mii { + pins = "gpio36", "gpio37", "gpio38", "gpio39"; + function = "alt5"; + }; + }; + + pcm-gpio50 { + phandle = <0x97>; + + pins-pcm { + pins = "gpio50", "gpio51", "gpio52", "gpio53"; + function = "alt2"; + }; + }; + + pwm0-0-gpio12 { + phandle = <0x98>; + + pin-pwm { + pins = "gpio12"; + function = "alt0"; + bias-disable; + }; + }; + + pwm0-0-gpio18 { + phandle = <0x99>; + + pin-pwm { + pins = "gpio18"; + function = "alt5"; + bias-disable; + }; + }; + + pwm1-0-gpio40 { + phandle = <0x28>; + + pin-pwm { + pins = "gpio40"; + function = "alt0"; + bias-disable; + }; + }; + + pwm0-1-gpio13 { + phandle = <0x9a>; + + pin-pwm { + pins = "gpio13"; + function = "alt0"; + bias-disable; + }; + }; + + pwm0-1-gpio19 { + phandle = <0x9b>; + + pin-pwm { + pins = "gpio19"; + function = "alt5"; + bias-disable; + }; + }; + + pwm1-1-gpio41 { + phandle = <0x29>; + + pin-pwm { + pins = "gpio41"; + function = "alt0"; + bias-disable; + }; + }; + + pwm0-1-gpio45 { + phandle = <0x9c>; + + pin-pwm { + pins = "gpio45"; + function = "alt0"; + bias-disable; + }; + }; + + pwm0-0-gpio52 { + phandle = <0x9d>; + + pin-pwm { + pins = "gpio52"; + function = "alt1"; + bias-disable; + }; + }; + + pwm0-1-gpio53 { + phandle = <0x9e>; + + pin-pwm { + pins = "gpio53"; + function = "alt1"; + bias-disable; + }; + }; + + rgmii-gpio35 { + phandle = <0x9f>; + + pin-start-stop { + pins = "gpio35"; + function = "alt4"; + }; + + pin-rx-ok { + pins = "gpio36"; + function = "alt4"; + }; + }; + + rgmii-irq-gpio34 { + phandle = <0xa0>; + + pin-irq { + pins = "gpio34"; + function = "alt5"; + }; + }; + + rgmii-irq-gpio39 { + phandle = <0xa1>; + + pin-irq { + pins = "gpio39"; + function = "alt4"; + }; + }; + + rgmii-mdio-gpio28 { + phandle = <0xa2>; + + pins-mdio { + pins = "gpio28", "gpio29"; + function = "alt5"; + }; + }; + + rgmii-mdio-gpio37 { + phandle = <0xa3>; + + pins-mdio { + pins = "gpio37", "gpio38"; + function = "alt4"; + }; + }; + + spi0-gpio46 { + phandle = <0xa4>; + + pins-spi { + pins = "gpio46", "gpio47", "gpio48", "gpio49"; + function = "alt2"; + }; + }; + + spi2-gpio46 { + phandle = <0xa5>; + + pins-spi { + pins = "gpio46", "gpio47", "gpio48", "gpio49", "gpio50"; + function = "alt5"; + }; + }; + + spi3-gpio0 { + phandle = <0xa6>; + + pins-spi { + pins = "gpio0", "gpio1", "gpio2", "gpio3"; + function = "alt3"; + }; + }; + + spi4-gpio4 { + phandle = <0xa7>; + + pins-spi { + pins = "gpio4", "gpio5", "gpio6", "gpio7"; + function = "alt3"; + }; + }; + + spi5-gpio12 { + phandle = <0xa8>; + + pins-spi { + pins = "gpio12", "gpio13", "gpio14", "gpio15"; + function = "alt3"; + }; + }; + + spi6-gpio18 { + phandle = <0xa9>; + + pins-spi { + pins = "gpio18", "gpio19", "gpio20", "gpio21"; + function = "alt3"; + }; + }; + + uart2-gpio0 { + phandle = <0xaa>; + + pin-tx { + pins = "gpio0"; + function = "alt4"; + bias-disable; + }; + + pin-rx { + pins = "gpio1"; + function = "alt4"; + bias-pull-up; + }; + }; + + uart2-ctsrts-gpio2 { + phandle = <0xab>; + + pin-cts { + pins = "gpio2"; + function = "alt4"; + bias-pull-up; + }; + + pin-rts { + pins = "gpio3"; + function = "alt4"; + bias-disable; + }; + }; + + uart3-gpio4 { + phandle = <0xac>; + + pin-tx { + pins = "gpio4"; + function = "alt4"; + bias-disable; + }; + + pin-rx { + pins = "gpio5"; + function = "alt4"; + bias-pull-up; + }; + }; + + uart3-ctsrts-gpio6 { + phandle = <0xad>; + + pin-cts { + pins = "gpio6"; + function = "alt4"; + bias-pull-up; + }; + + pin-rts { + pins = "gpio7"; + function = "alt4"; + bias-disable; + }; + }; + + uart4-gpio8 { + phandle = <0xae>; + + pin-tx { + pins = "gpio8"; + function = "alt4"; + bias-disable; + }; + + pin-rx { + pins = "gpio9"; + function = "alt4"; + bias-pull-up; + }; + }; + + uart4-ctsrts-gpio10 { + phandle = <0xaf>; + + pin-cts { + pins = "gpio10"; + function = "alt4"; + bias-pull-up; + }; + + pin-rts { + pins = "gpio11"; + function = "alt4"; + bias-disable; + }; + }; + + uart5-gpio12 { + phandle = <0xb0>; + + pin-tx { + pins = "gpio12"; + function = "alt4"; + bias-disable; + }; + + pin-rx { + pins = "gpio13"; + function = "alt4"; + bias-pull-up; + }; + }; + + uart5-ctsrts-gpio14 { + phandle = <0xb1>; + + pin-cts { + pins = "gpio14"; + function = "alt4"; + bias-pull-up; + }; + + pin-rts { + pins = "gpio15"; + function = "alt4"; + bias-disable; + }; + }; + + dpi_18bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + brcm,pull = <0x00>; + phandle = <0xb2>; + }; + + dpi_18bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18 0x19>; + brcm,function = <0x06>; + phandle = <0xb3>; + }; + + dpi_18bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0xb4>; + }; + + dpi_18bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13 0x14 0x15>; + brcm,function = <0x06>; + phandle = <0xb5>; + }; + + dpi_16bit_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0xb6>; + }; + + dpi_16bit_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x12 0x13>; + brcm,function = <0x06>; + phandle = <0xb7>; + }; + + dpi_16bit_cpadhi_gpio0 { + brcm,pins = <0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0xb8>; + }; + + dpi_16bit_cpadhi_gpio2 { + brcm,pins = <0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x0c 0x0d 0x0e 0x0f 0x10 0x11 0x14 0x15 0x16 0x17 0x18>; + brcm,function = <0x06>; + phandle = <0xb9>; + }; + + gpioout { + brcm,pins = <0x06>; + brcm,function = <0x01>; + phandle = <0xba>; + }; + + alt0 { + brcm,pins = <0x04 0x05 0x07 0x08 0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0xbb>; + }; + + spi0_pins { + brcm,pins = <0x09 0x0a 0x0b>; + brcm,function = <0x04>; + phandle = <0x0e>; + }; + + spi0_cs_pins { + brcm,pins = <0x08 0x07>; + brcm,function = <0x01>; + phandle = <0x0f>; + }; + + spi3_pins { + brcm,pins = <0x01 0x02 0x03>; + brcm,function = <0x07>; + phandle = <0x1c>; + }; + + spi3_cs_pins { + brcm,pins = <0x00 0x18>; + brcm,function = <0x01>; + phandle = <0x1d>; + }; + + spi4_pins { + brcm,pins = <0x05 0x06 0x07>; + brcm,function = <0x07>; + phandle = <0x1e>; + }; + + spi4_cs_pins { + brcm,pins = <0x04 0x19>; + brcm,function = <0x01>; + phandle = <0x1f>; + }; + + spi5_pins { + brcm,pins = <0x0d 0x0e 0x0f>; + brcm,function = <0x07>; + phandle = <0x20>; + }; + + spi5_cs_pins { + brcm,pins = <0x0c 0x1a>; + brcm,function = <0x01>; + phandle = <0x21>; + }; + + spi6_pins { + brcm,pins = <0x13 0x14 0x15>; + brcm,function = <0x07>; + phandle = <0x22>; + }; + + spi6_cs_pins { + brcm,pins = <0x12 0x1b>; + brcm,function = <0x01>; + phandle = <0x23>; + }; + + i2c0 { + brcm,pins = <0x00 0x01>; + brcm,function = <0x04>; + brcm,pull = <0x02>; + phandle = <0xbc>; + }; + + i2c1 { + brcm,pins = <0x02 0x03>; + brcm,function = <0x04>; + brcm,pull = <0x02>; + phandle = <0x15>; + }; + + i2c3 { + brcm,pins = <0x04 0x05>; + brcm,function = <0x02>; + brcm,pull = <0x02>; + phandle = <0x24>; + }; + + i2c4 { + brcm,pins = <0x08 0x09>; + brcm,function = <0x02>; + brcm,pull = <0x02>; + phandle = <0x25>; + }; + + i2c5 { + brcm,pins = <0x0c 0x0d>; + brcm,function = <0x02>; + brcm,pull = <0x02>; + phandle = <0x26>; + }; + + i2c6 { + brcm,pins = <0x16 0x17>; + brcm,function = <0x02>; + brcm,pull = <0x02>; + phandle = <0x27>; + }; + + i2s { + brcm,pins = <0x12 0x13 0x14 0x15>; + brcm,function = <0x04>; + phandle = <0x0d>; + }; + + sdio_pins { + brcm,pins = <0x22 0x23 0x24 0x25 0x26 0x27>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02 0x02 0x02 0x02 0x02>; + phandle = <0x31>; + }; + + uart2_pins { + brcm,pins = <0x00 0x01>; + brcm,function = <0x03>; + brcm,pull = <0x00 0x02>; + phandle = <0x18>; + }; + + uart3_pins { + brcm,pins = <0x04 0x05>; + brcm,function = <0x03>; + brcm,pull = <0x00 0x02>; + phandle = <0x19>; + }; + + uart4_pins { + brcm,pins = <0x08 0x09>; + brcm,function = <0x03>; + brcm,pull = <0x00 0x02>; + phandle = <0x1a>; + }; + + uart5_pins { + brcm,pins = <0x0c 0x0d>; + brcm,function = <0x03>; + brcm,pull = <0x00 0x02>; + phandle = <0x1b>; + }; + + bt_pins { + brcm,pins = "-"; + brcm,function = <0x00>; + brcm,pull = <0x02>; + phandle = <0x0a>; + }; + + uart0_pins { + brcm,pins = <0x20 0x21>; + brcm,function = <0x07>; + brcm,pull = <0x00 0x02>; + phandle = <0x09>; + }; + + uart1_pins { + brcm,pins; + brcm,function; + brcm,pull; + phandle = <0x12>; + }; + + uart1_bt_pins { + brcm,pins = <0x20 0x21 0x1e 0x1f>; + brcm,function = <0x02>; + brcm,pull = <0x00 0x02 0x02 0x00>; + phandle = <0xbd>; + }; + + audio_pins { + brcm,pins = <0x28 0x29>; + brcm,function = <0x04>; + brcm,pull = <0x00>; + phandle = <0x36>; + }; + }; + + serial@7e201000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x7e201000 0x200>; + interrupts = <0x00 0x79 0x04>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x241011>; + status = "okay"; + cts-event-workaround; + pinctrl-names = "default"; + pinctrl-0 = <0x09 0x0a>; + uart-has-rtscts; + skip-init; + phandle = <0x43>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <0x2dc6c0>; + shutdown-gpios = <0x0b 0x00 0x00>; + local-bd-address = [00 00 00 00 00 00]; + fallback-bd-address; + status = "okay"; + phandle = <0x41>; + }; + }; + + mmc@7e202000 { + compatible = "brcm,bcm2835-sdhost"; + reg = <0x7e202000 0x100>; + interrupts = <0x00 0x78 0x04>; + clocks = <0x08 0x14>; + status = "disabled"; + dmas = <0x0c 0x2000000d>; + dma-names = "rx-tx"; + bus-width = <0x04>; + brcm,overclock-50 = <0x00>; + brcm,pio-limit = <0x01>; + firmware = <0x06>; + phandle = <0x4b>; + }; + + i2s@7e203000 { + compatible = "brcm,bcm2835-i2s"; + reg = <0x7e203000 0x24>; + clocks = <0x08 0x1f>; + status = "disabled"; + #sound-dai-cells = <0x00>; + dmas = <0x0c 0x02 0x0c 0x03>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <0x0d>; + phandle = <0x45>; + }; + + spi@7e204000 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204000 0x200>; + interrupts = <0x00 0x76 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + dmas = <0x0c 0x06 0x0c 0x07>; + dma-names = "tx", "rx"; + pinctrl-names = "default"; + pinctrl-0 = <0x0e 0x0f>; + cs-gpios = <0x07 0x08 0x01 0x07 0x07 0x01>; + phandle = <0x46>; + + spidev@0 { + compatible = "spidev"; + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0xbe>; + }; + + spidev@1 { + compatible = "spidev"; + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + spi-max-frequency = <0x7735940>; + phandle = <0xbf>; + }; + }; + + i2c@7e205000 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205000 0x200>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + clock-frequency = <0x186a0>; + phandle = <0x32>; + }; + + dpi@7e208000 { + compatible = "brcm,bcm2835-dpi"; + reg = <0x7e208000 0x8c>; + clocks = <0x08 0x14 0x08 0x2c>; + clock-names = "core", "pixel"; + status = "disabled"; + phandle = <0xc0>; + }; + + dsi@7e209000 { + compatible = "brcm,bcm2835-dsi0"; + reg = <0x7e209000 0x78>; + interrupts = <0x00 0x64 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x22 0x08 0x2f 0x08 0x31>; + clock-names = "phy", "escape", "pixel"; + clock-output-names = "dsi0_byte", "dsi0_ddr2", "dsi0_ddr"; + status = "disabled"; + power-domains = <0x10 0x11>; + phandle = <0x04>; + }; + + aux@7e215000 { + compatible = "brcm,bcm2835-aux"; + #clock-cells = <0x01>; + reg = <0x7e215000 0x08>; + clocks = <0x08 0x14>; + phandle = <0x11>; + }; + + serial@7e215040 { + compatible = "brcm,bcm2835-aux-uart"; + reg = <0x7e215040 0x40>; + interrupts = <0x00 0x5d 0x04>; + clocks = <0x11 0x00>; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x12>; + skip-init; + phandle = <0x44>; + + bluetooth { + compatible = "brcm,bcm43438-bt"; + max-speed = <0x38400>; + shutdown-gpios = <0x0b 0x00 0x00>; + local-bd-address = [00 00 00 00 00 00]; + fallback-bd-address; + status = "disabled"; + phandle = <0x42>; + }; + }; + + spi@7e215080 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e215080 0x40>; + interrupts = <0x00 0x5d 0x04>; + clocks = <0x11 0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0xc1>; + }; + + spi@7e2150c0 { + compatible = "brcm,bcm2835-aux-spi"; + reg = <0x7e2150c0 0x40>; + interrupts = <0x00 0x5d 0x04>; + clocks = <0x11 0x02>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + phandle = <0xc2>; + }; + + pwm@7e20c000 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c000 0x28>; + clocks = <0x08 0x1e>; + assigned-clocks = <0x08 0x1e>; + assigned-clock-rates = <0x2faf080>; + #pwm-cells = <0x03>; + status = "disabled"; + phandle = <0xc3>; + }; + + mmc@7e300000 { + compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x00 0x7e 0x04>; + clocks = <0x08 0x1c>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x13>; + bus-width = <0x04>; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + phandle = <0x4c>; + }; + + hvs@7e400000 { + compatible = "brcm,bcm2711-hvs"; + reg = <0x7e400000 0x8000>; + interrupts = <0x00 0x61 0x04>; + status = "disabled"; + clocks = <0x14 0x04>; + phandle = <0xc4>; + }; + + dsi@7e700000 { + compatible = "brcm,bcm2711-dsi1"; + reg = <0x7e700000 0x8c>; + interrupts = <0x00 0x6c 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + clocks = <0x08 0x23 0x08 0x30 0x08 0x32>; + clock-names = "phy", "escape", "pixel"; + clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr"; + status = "disabled"; + power-domains = <0x10 0x12>; + phandle = <0x05>; + }; + + i2c@7e804000 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e804000 0x1000>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x15>; + clock-frequency = <0x186a0>; + phandle = <0x48>; + }; + + usb@7e980000 { + compatible = "brcm,bcm2708-usb"; + reg = <0x7e980000 0x10000 0x7e00b200 0x200>; + interrupts = <0x00 0x49 0x04 0x00 0x28 0x04>; + #address-cells = <0x01>; + #size-cells = <0x00>; + clocks = <0x16>; + clock-names = "otg"; + phys = <0x17>; + phy-names = "usb2-phy"; + interrupt-names = "usb", "soft"; + power-domains = <0x10 0x06>; + status = "disabled"; + phandle = <0xc5>; + }; + + interrupt-controller@40000000 { + compatible = "brcm,bcm2836-l1-intc"; + reg = <0x40000000 0x100>; + phandle = <0xc6>; + }; + + interrupt-controller@40041000 { + interrupt-controller; + #interrupt-cells = <0x03>; + compatible = "arm,gic-400"; + reg = <0x40041000 0x1000 0x40042000 0x2000 0x40044000 0x2000 0x40046000 0x2000>; + interrupts = <0x01 0x09 0xf04>; + phandle = <0x01>; + }; + + avs-monitor@7d5d2000 { + compatible = "brcm,bcm2711-avs-monitor", "syscon", "simple-mfd"; + reg = <0x7d5d2000 0xf00>; + phandle = <0xc7>; + + thermal { + compatible = "brcm,bcm2711-thermal"; + #thermal-sensor-cells = <0x00>; + phandle = <0x02>; + }; + }; + + dma-controller@7e007000 { + compatible = "brcm,bcm2835-dma"; + reg = <0x7e007000 0xb00>; + interrupts = <0x00 0x50 0x04 0x00 0x51 0x04 0x00 0x52 0x04 0x00 0x53 0x04 0x00 0x54 0x04 0x00 0x55 0x04 0x00 0x56 0x04 0x00 0x57 0x04 0x00 0x57 0x04 0x00 0x58 0x04 0x00 0x58 0x04>; + interrupt-names = "dma0", "dma1", "dma2", "dma3", "dma4", "dma5", "dma6", "dma7", "dma8", "dma9", "dma10"; + #dma-cells = <0x01>; + brcm,dma-channel-mask = <0x7f5>; + phandle = <0x0c>; + }; + + watchdog@7e100000 { + compatible = "brcm,bcm2711-pm", "brcm,bcm2835-pm-wdt"; + #power-domain-cells = <0x01>; + #reset-cells = <0x01>; + reg = <0x7e100000 0x114 0x7e00a000 0x24 0x7ec11000 0x20>; + reg-names = "pm", "asb", "rpivid_asb"; + clocks = <0x08 0x15 0x08 0x1d 0x08 0x17 0x08 0x16>; + clock-names = "v3d", "peri_image", "h264", "isp"; + system-power-controller; + phandle = <0x49>; + }; + + rng@7e104000 { + compatible = "brcm,bcm2711-rng200"; + reg = <0x7e104000 0x28>; + status = "okay"; + phandle = <0x4a>; + }; + + serial@7e201400 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x7e201400 0x200>; + interrupts = <0x00 0x79 0x04>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x241011>; + status = "disabled"; + pinctrl-0 = <0x18>; + pinctrl-names = "default"; + phandle = <0xc8>; + }; + + serial@7e201600 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x7e201600 0x200>; + interrupts = <0x00 0x79 0x04>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x241011>; + status = "disabled"; + pinctrl-0 = <0x19>; + pinctrl-names = "default"; + phandle = <0xc9>; + }; + + serial@7e201800 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x7e201800 0x200>; + interrupts = <0x00 0x79 0x04>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x241011>; + status = "disabled"; + pinctrl-0 = <0x1a>; + pinctrl-names = "default"; + phandle = <0xca>; + }; + + serial@7e201a00 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x7e201a00 0x200>; + interrupts = <0x00 0x79 0x04>; + clocks = <0x08 0x13 0x08 0x14>; + clock-names = "uartclk", "apb_pclk"; + arm,primecell-periphid = <0x241011>; + status = "disabled"; + pinctrl-0 = <0x1b>; + pinctrl-names = "default"; + phandle = <0xcb>; + }; + + spi@7e204600 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204600 0x200>; + interrupts = <0x00 0x76 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x1c 0x1d>; + pinctrl-names = "default"; + phandle = <0xcc>; + }; + + spi@7e204800 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204800 0x200>; + interrupts = <0x00 0x76 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x1e 0x1f>; + pinctrl-names = "default"; + phandle = <0xcd>; + }; + + spi@7e204a00 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204a00 0x200>; + interrupts = <0x00 0x76 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x20 0x21>; + pinctrl-names = "default"; + phandle = <0xce>; + }; + + spi@7e204c00 { + compatible = "brcm,bcm2835-spi"; + reg = <0x7e204c00 0x200>; + interrupts = <0x00 0x76 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x22 0x23>; + pinctrl-names = "default"; + phandle = <0xcf>; + }; + + i2c@7e205600 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205600 0x200>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x24>; + pinctrl-names = "default"; + phandle = <0xd0>; + }; + + i2c@7e205800 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205800 0x200>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x25>; + pinctrl-names = "default"; + phandle = <0xd1>; + }; + + i2c@7e205a00 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205a00 0x200>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x26>; + pinctrl-names = "default"; + phandle = <0xd2>; + }; + + i2c@7e205c00 { + compatible = "brcm,bcm2711-i2c", "brcm,bcm2835-i2c"; + reg = <0x7e205c00 0x200>; + interrupts = <0x00 0x75 0x04>; + clocks = <0x08 0x14>; + #address-cells = <0x01>; + #size-cells = <0x00>; + status = "disabled"; + pinctrl-0 = <0x27>; + pinctrl-names = "default"; + phandle = <0xd3>; + }; + + pixelvalve@7e206000 { + compatible = "brcm,bcm2711-pixelvalve0"; + reg = <0x7e206000 0x100>; + interrupts = <0x00 0x6d 0x04>; + status = "disabled"; + phandle = <0xd4>; + }; + + pixelvalve@7e207000 { + compatible = "brcm,bcm2711-pixelvalve1"; + reg = <0x7e207000 0x100>; + interrupts = <0x00 0x6e 0x04>; + status = "disabled"; + phandle = <0xd5>; + }; + + pixelvalve@7e20a000 { + compatible = "brcm,bcm2711-pixelvalve2"; + reg = <0x7e20a000 0x100>; + interrupts = <0x00 0x65 0x04>; + status = "disabled"; + phandle = <0xd6>; + }; + + pwm@7e20c800 { + compatible = "brcm,bcm2835-pwm"; + reg = <0x7e20c800 0x28>; + clocks = <0x08 0x1e>; + assigned-clocks = <0x08 0x1e>; + assigned-clock-rates = <0x2faf080>; + #pwm-cells = <0x03>; + status = "disabled"; + pinctrl-names = "default"; + pinctrl-0 = <0x28 0x29>; + phandle = <0xd7>; + }; + + pixelvalve@7e216000 { + compatible = "brcm,bcm2711-pixelvalve4"; + reg = <0x7e216000 0x100>; + interrupts = <0x00 0x6e 0x04>; + status = "disabled"; + phandle = <0xd8>; + }; + + pixelvalve@7ec12000 { + compatible = "brcm,bcm2711-pixelvalve3"; + reg = <0x7ec12000 0x100>; + interrupts = <0x00 0x6a 0x04>; + status = "disabled"; + phandle = <0xd9>; + }; + + vec@7ec13000 { + compatible = "brcm,bcm2711-vec"; + reg = <0x7ec13000 0x1000>; + clocks = <0x14 0x0f>; + interrupts = <0x00 0x7b 0x04>; + status = "disabled"; + power-domains = <0x10 0x07>; + phandle = <0xda>; + }; + + clock@7ef00000 { + compatible = "brcm,brcm2711-dvp"; + reg = <0x7ef00000 0x10>; + clocks = <0x2a>; + #clock-cells = <0x01>; + #reset-cells = <0x01>; + status = "disabled"; + phandle = <0x2b>; + }; + + interrupt-controller@7ef00100 { + compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; + reg = <0x7ef00100 0x30>; + interrupts = <0x00 0x60 0x01>; + interrupt-controller; + #interrupt-cells = <0x01>; + status = "disabled"; + phandle = <0x2c>; + }; + + hdmi@7ef00700 { + compatible = "brcm,bcm2711-hdmi0"; + reg = <0x7ef00700 0x300 0x7ef00300 0x200 0x7ef00f00 0x80 0x7ef00f80 0x80 0x7ef01b00 0x200 0x7ef01f00 0x400 0x7ef00200 0x80 0x7ef04300 0x100 0x7ef20000 0x100 0x7ef00100 0x30>; + reg-names = "hdmi", "dvp", "phy", "rm", "packet", "metadata", "csc", "cec", "hd", "intr2"; + clock-names = "hdmi", "bvb", "audio", "cec"; + resets = <0x2b 0x00>; + interrupt-parent = <0x2c>; + interrupts = <0x00 0x01 0x02 0x03 0x04 0x05>; + interrupt-names = "cec-tx", "cec-rx", "cec-low", "wakeup", "hpd-connected", "hpd-removed"; + ddc = <0x2d>; + dmas = <0x2e 0x41fa000a>; + dma-names = "audio-rx"; + status = "disabled"; + clocks = <0x14 0x0d 0x14 0x0e 0x2b 0x00 0x2f>; + wifi-2.4ghz-coexistence; + phandle = <0x55>; + }; + + i2c@7ef04500 { + compatible = "brcm,bcm2711-hdmi-i2c"; + reg = <0x7ef04500 0x100 0x7ef00b00 0x300>; + reg-names = "bsc", "auto-i2c"; + clock-frequency = <0x17cdc>; + status = "disabled"; + phandle = <0x2d>; + }; + + hdmi@7ef05700 { + compatible = "brcm,bcm2711-hdmi1"; + reg = <0x7ef05700 0x300 0x7ef05300 0x200 0x7ef05f00 0x80 0x7ef05f80 0x80 0x7ef06b00 0x200 0x7ef06f00 0x400 0x7ef00280 0x80 0x7ef09300 0x100 0x7ef20000 0x100 0x7ef00100 0x30>; + reg-names = "hdmi", "dvp", "phy", "rm", "packet", "metadata", "csc", "cec", "hd", "intr2"; + ddc = <0x30>; + clock-names = "hdmi", "bvb", "audio", "cec"; + resets = <0x2b 0x01>; + interrupt-parent = <0x2c>; + interrupts = <0x08 0x07 0x06 0x09 0x0a 0x0b>; + interrupt-names = "cec-tx", "cec-rx", "cec-low", "wakeup", "hpd-connected", "hpd-removed"; + dmas = <0x2e 0x41fa0011>; + dma-names = "audio-rx"; + status = "disabled"; + clocks = <0x14 0x0d 0x14 0x0e 0x2b 0x01 0x2f>; + wifi-2.4ghz-coexistence; + phandle = <0x56>; + }; + + i2c@7ef09500 { + compatible = "brcm,bcm2711-hdmi-i2c"; + reg = <0x7ef09500 0x100 0x7ef05b00 0x300>; + reg-names = "bsc", "auto-i2c"; + clock-frequency = <0x17cdc>; + status = "disabled"; + phandle = <0x30>; + }; + + mmcnr@7e300000 { + compatible = "brcm,bcm2835-mmc", "brcm,bcm2835-sdhci"; + reg = <0x7e300000 0x100>; + interrupts = <0x00 0x7e 0x04>; + clocks = <0x08 0x1c>; + dmas = <0x0c 0x0b>; + dma-names = "rx-tx"; + brcm,overclock-50 = <0x00>; + non-removable; + status = "okay"; + pinctrl-names = "default"; + pinctrl-0 = <0x31>; + bus-width = <0x04>; + phandle = <0x4d>; + }; + + firmwarekms@7e600000 { + compatible = "raspberrypi,rpi-firmware-kms-2711"; + reg = <0x7e600000 0x100>; + interrupts = <0x00 0x70 0x04>; + brcm,firmware = <0x06>; + status = "disabled"; + phandle = <0xdb>; + }; + + smi@7e600000 { + compatible = "brcm,bcm2835-smi"; + reg = <0x7e600000 0x100>; + interrupts = <0x00 0x70 0x04>; + clocks = <0x08 0x2a>; + assigned-clocks = <0x08 0x2a>; + assigned-clock-rates = <0x7735940>; + dmas = <0x0c 0x04>; + dma-names = "rx-tx"; + status = "disabled"; + phandle = <0xdc>; + }; + + csi@7e800000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e800000 0x800 0x7e802000 0x04>; + interrupts = <0x00 0x66 0x04>; + clocks = <0x08 0x2d 0x14 0x04>; + clock-names = "lp", "vpu"; + power-domains = <0x10 0x0c>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + phandle = <0x51>; + }; + + csi@7e801000 { + compatible = "brcm,bcm2835-unicam"; + reg = <0x7e801000 0x800 0x7e802004 0x04>; + interrupts = <0x00 0x67 0x04>; + clocks = <0x08 0x2e 0x14 0x04>; + clock-names = "lp", "vpu"; + power-domains = <0x10 0x0d>; + #address-cells = <0x01>; + #size-cells = <0x00>; + #clock-cells = <0x01>; + status = "disabled"; + brcm,num-data-lanes = <0x02>; + phandle = <0x50>; + }; + + axiperf { + compatible = "brcm,bcm2711-axiperf"; + reg = <0x7e009800 0x100 0x7ee08000 0x100>; + firmware = <0x06>; + status = "disabled"; + phandle = <0x4e>; + }; + + i2c0mux { + compatible = "i2c-mux-pinctrl"; + #address-cells = <0x01>; + #size-cells = <0x00>; + i2c-parent = <0x32>; + status = "disabled"; + pinctrl-names = "i2c0", "i2c_csi_dsi"; + pinctrl-0 = <0x33>; + pinctrl-1 = <0x34>; + phandle = <0x47>; + + i2c@0 { + reg = <0x00>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0xdd>; + }; + + i2c@1 { + reg = <0x01>; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0xde>; + }; + }; + + firmware { + compatible = "raspberrypi,bcm2835-firmware", "simple-mfd"; + #address-cells = <0x01>; + #size-cells = <0x01>; + mboxes = <0x35>; + dma-ranges; + phandle = <0x06>; + + clocks { + compatible = "raspberrypi,firmware-clocks"; + #clock-cells = <0x01>; + phandle = <0x14>; + }; + + gpio { + compatible = "raspberrypi,firmware-gpio"; + gpio-controller; + #gpio-cells = <0x02>; + status = "okay"; + gpio-line-names = "BT_ON", "WL_ON", "PWR_LED_OFF", "GLOBAL_RESET", "VDD_SD_IO_SEL", "CAM_GPIO", "SD_PWR_ON", "SD_OC_N"; + phandle = <0x0b>; + }; + + reset { + compatible = "raspberrypi,firmware-reset"; + #reset-cells = <0x01>; + phandle = <0x3f>; + }; + + vcio { + compatible = "raspberrypi,vcio"; + phandle = <0xdf>; + }; + }; + + power { + compatible = "raspberrypi,bcm2835-power"; + firmware = <0x06>; + #power-domain-cells = <0x01>; + phandle = <0x10>; + }; + + mailbox@7e00b840 { + compatible = "brcm,bcm2711-vchiq"; + reg = <0x7e00b840 0x3c>; + interrupts = <0x00 0x22 0x04>; + pinctrl-names = "default"; + pinctrl-0 = <0x36>; + phandle = <0xe0>; + }; + + gpiomem { + compatible = "brcm,bcm2835-gpiomem"; + reg = <0x7e200000 0x1000>; + }; + + fb { + compatible = "brcm,bcm2708-fb"; + firmware = <0x06>; + status = "okay"; + phandle = <0xe1>; + }; + + sound { + status = "disabled"; + phandle = <0xe2>; + }; + + nvmem { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x01>; + + nvmem_otp { + compatible = "raspberrypi,rpi-otp"; + firmware = <0x06>; + reg = <0x00 0xa6>; + status = "okay"; + phandle = <0xe3>; + }; + + nvmem_cust { + compatible = "raspberrypi,rpi-otp"; + firmware = <0x06>; + reg = <0x01 0x08>; + status = "okay"; + phandle = <0x57>; + }; + + nvmem_priv { + compatible = "raspberrypi,rpi-otp"; + firmware = <0x06>; + reg = <0x03 0x08>; + status = "okay"; + phandle = <0x58>; + }; + }; + }; + + clocks { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x00>; + + clk-osc { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "osc"; + clock-frequency = <0x337f980>; + phandle = <0x03>; + }; + + clk-usb { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + clock-output-names = "otg"; + clock-frequency = <0x1c9c3800>; + phandle = <0x16>; + }; + }; + + phy { + compatible = "usb-nop-xceiv"; + #phy-cells = <0x00>; + phandle = <0x17>; + }; + + gpu { + compatible = "brcm,bcm2711-vc5"; + status = "disabled"; + raspberrypi,firmware = <0x06>; + phandle = <0xe4>; + }; + + clk-27M { + #clock-cells = <0x00>; + compatible = "fixed-clock"; + clock-frequency = <0x19bfcc0>; + clock-output-names = "27MHz-clock"; + phandle = <0x2f>; + }; + + clk-108M { + #clock-cells = <0x00>; + compatible = "fixed-clock"; + clock-frequency = <0x66ff300>; + clock-output-names = "108MHz-clock"; + phandle = <0x2a>; + }; + + emmc2bus { + compatible = "simple-bus"; + #address-cells = <0x02>; + #size-cells = <0x01>; + ranges = <0x00 0x7e000000 0x00 0xfe000000 0x1800000>; + dma-ranges = <0x00 0xc0000000 0x00 0x00 0x40000000>; + phandle = <0xe5>; + + mmc@7e340000 { + compatible = "brcm,bcm2711-emmc2"; + reg = <0x00 0x7e340000 0x100>; + interrupts = <0x00 0x7e 0x04>; + clocks = <0x08 0x33>; + status = "okay"; + vqmmc-supply = <0x37>; + vmmc-supply = <0x38>; + broken-cd; + mmc-ddr-3_3v; + phandle = <0x59>; + }; + }; + + arm-pmu { + compatible = "arm,cortex-a72-pmu", "arm,armv8-pmuv3", "arm,cortex-a7-pmu"; + interrupts = <0x00 0x10 0x04 0x00 0x11 0x04 0x00 0x12 0x04 0x00 0x13 0x04>; + interrupt-affinity = <0x39 0x3a 0x3b 0x3c>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <0x01 0x0d 0xf08 0x01 0x0e 0xf08 0x01 0x0b 0xf08 0x01 0x0a 0xf08>; + arm,cpu-registers-not-fw-configured; + }; + + cpus { + #address-cells = <0x01>; + #size-cells = <0x00>; + enable-method = "brcm,bcm2836-smp"; + phandle = <0xe6>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x00>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xd8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x100>; + i-cache-size = <0xc000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x3d>; + phandle = <0x39>; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x01>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x100>; + i-cache-size = <0xc000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x3d>; + phandle = <0x3a>; + }; + + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x02>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xe8>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x100>; + i-cache-size = <0xc000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x3d>; + phandle = <0x3b>; + }; + + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a72"; + reg = <0x03>; + enable-method = "spin-table"; + cpu-release-addr = <0x00 0xf0>; + d-cache-size = <0x8000>; + d-cache-line-size = <0x40>; + d-cache-sets = <0x100>; + i-cache-size = <0xc000>; + i-cache-line-size = <0x40>; + i-cache-sets = <0x100>; + next-level-cache = <0x3d>; + phandle = <0x3c>; + }; + + l2-cache0 { + compatible = "cache"; + cache-unified; + cache-size = <0x100000>; + cache-line-size = <0x40>; + cache-sets = <0x400>; + cache-level = <0x02>; + phandle = <0x3d>; + }; + }; + + scb { + compatible = "simple-bus"; + #address-cells = <0x02>; + #size-cells = <0x02>; + ranges = <0x00 0x7c000000 0x00 0xfc000000 0x00 0x3800000 0x00 0x40000000 0x00 0xff800000 0x00 0x800000 0x06 0x00 0x06 0x00 0x00 0x80000000 0x00 0x00 0x00 0x00 0x00 0xfc000000>; + dma-ranges = <0x04 0x7c000000 0x00 0xfc000000 0x00 0x3800000 0x00 0x00 0x00 0x00 0x04 0x00>; + phandle = <0xe7>; + + pcie@7d500000 { + compatible = "brcm,bcm2711-pcie"; + reg = <0x00 0x7d500000 0x00 0x9310>; + device_type = "pci"; + #address-cells = <0x03>; + #interrupt-cells = <0x01>; + #size-cells = <0x02>; + interrupts = <0x00 0x93 0x04 0x00 0x94 0x04>; + interrupt-names = "pcie", "msi"; + interrupt-map-mask = <0x00 0x00 0x00 0x07>; + interrupt-map = <0x00 0x00 0x00 0x01 0x01 0x00 0x8f 0x04 0x00 0x00 0x00 0x02 0x01 0x00 0x90 0x04 0x00 0x00 0x00 0x03 0x01 0x00 0x91 0x04 0x00 0x00 0x00 0x04 0x01 0x00 0x92 0x04>; + msi-controller; + msi-parent = <0x3e>; + ranges = <0x2000000 0x00 0x80000000 0x06 0x00 0x00 0x80000000>; + dma-ranges = <0x2000000 0x00 0x00 0x00 0x00 0x00 0xc0000000>; + brcm,enable-ssc; + phandle = <0x3e>; + + pci@0,0 { + device_type = "pci"; + #address-cells = <0x03>; + #size-cells = <0x02>; + ranges; + reg = <0x00 0x00 0x00 0x00 0x00>; + + usb@0,0 { + reg = <0x00 0x00 0x00 0x00 0x00>; + resets = <0x3f 0x00>; + }; + }; + }; + + ethernet@7d580000 { + compatible = "brcm,bcm2711-genet-v5"; + reg = <0x00 0x7d580000 0x00 0x10000>; + #address-cells = <0x01>; + #size-cells = <0x01>; + interrupts = <0x00 0x9d 0x04 0x00 0x9e 0x04>; + status = "okay"; + phy-handle = <0x40>; + phy-mode = "rgmii-rxid"; + phandle = <0xe8>; + + mdio@e14 { + compatible = "brcm,genet-mdio-v5"; + reg = <0xe14 0x08>; + reg-names = "mdio"; + #address-cells = <0x01>; + #size-cells = <0x00>; + phandle = <0xe9>; + + ethernet-phy@1 { + reg = <0x01>; + led-modes = <0x00 0x08>; + phandle = <0x40>; + }; + }; + }; + + dma@7e007b00 { + compatible = "brcm,bcm2711-dma"; + reg = <0x00 0x7e007b00 0x00 0x400>; + interrupts = <0x00 0x59 0x04 0x00 0x5a 0x04 0x00 0x5b 0x04 0x00 0x5c 0x04>; + interrupt-names = "dma11", "dma12", "dma13", "dma14"; + #dma-cells = <0x01>; + brcm,dma-channel-mask = <0x7000>; + phandle = <0x2e>; + }; + + xhci@7e9c0000 { + compatible = "generic-xhci"; + status = "disabled"; + reg = <0x00 0x7e9c0000 0x00 0x100000>; + interrupts = <0x00 0xb0 0x04>; + power-domains = <0x10 0x06>; + phandle = <0xea>; + }; + + codec@7eb10000 { + compatible = "raspberrypi,rpivid-vid-decoder"; + reg = <0x00 0x7eb10000 0x00 0x1000 0x00 0x7eb00000 0x00 0x10000>; + reg-names = "intc", "hevc"; + interrupts = <0x00 0x62 0x04>; + clocks = <0x14 0x0b>; + clock-names = "hevc"; + }; + }; + + cam1_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam1-reg"; + enable-active-high; + status = "okay"; + gpio = <0x0b 0x05 0x00>; + phandle = <0x53>; + }; + + cam1_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0xeb>; + }; + + cam0_regulator { + compatible = "regulator-fixed"; + regulator-name = "cam0-reg"; + enable-active-high; + status = "disabled"; + phandle = <0xec>; + }; + + cam0_clk { + compatible = "fixed-clock"; + #clock-cells = <0x00>; + status = "disabled"; + phandle = <0xed>; + }; + + cam_dummy_reg { + compatible = "regulator-fixed"; + regulator-name = "cam-dummy-reg"; + status = "okay"; + phandle = <0x52>; + }; + + __overrides__ { + cam0-pwdn-ctrl; + cam0-pwdn; + cam0-led-ctrl; + cam0-led; + bdaddr = "", "", "", "Alocal-bd-address[", "", "", "", "Afallback-bd-address?=0", "", "", "", "Blocal-bd-address[", "", "", "", "Bfallback-bd-address?=0"; + krnbt = "", "", "", "Astatus"; + krnbt_baudrate = "", "", "", "Amax-speed:0", "", "", "", "Bmax-speed:0"; + cache_line_size; + uart0 = "", "", "", "Cstatus"; + uart1 = "", "", "", "Dstatus"; + i2s = "", "", "", "Estatus"; + spi = "", "", "", "Fstatus"; + i2c0 = "", "", "", "2status", "", "", "", "Gstatus"; + i2c1 = "", "", "", "Hstatus"; + i2c = "", "", "", "Hstatus"; + i2c_arm = "", "", "", "Hstatus"; + i2c_vc = "", "", "", "2status", "", "", "", "Gstatus"; + i2c0_baudrate = "", "", "", "2clock-frequency:0"; + i2c1_baudrate = "", "", "", "Hclock-frequency:0"; + i2c_baudrate = "", "", "", "Hclock-frequency:0"; + i2c_arm_baudrate = "", "", "", "Hclock-frequency:0"; + i2c_vc_baudrate = "", "", "", "2clock-frequency:0"; + watchdog = "", "", "", "Istatus"; + random = "", "", "", "Jstatus"; + sd_overclock = "", "", "", "Kbrcm,overclock-50:0"; + sd_force_pio = "", "", "", "Kbrcm,force-pio?"; + sd_pio_limit = "", "", "", "Kbrcm,pio-limit:0"; + sd_debug = "", "", "", "Kbrcm,debug"; + sdio_overclock = "", "", "", "Lbrcm,overclock-50:0", "", "", "", "Mbrcm,overclock-50:0"; + axiperf = "", "", "", "Nstatus"; + drm_fb0_vc4 = "", "", "", "Odrm-fb0=", "/gpu"; + drm_fb1_vc4 = "", "", "", "Odrm-fb1=", "/gpu"; + drm_fb2_vc4 = "", "", "", "Odrm-fb2=", "/gpu"; + cam1_sync = "", "", "", "Psync-gpios:0=", "", "", "", "\a", "", "", "Psync-gpios:4", "", "", "", "Psync-gpios:8=", "", "", "", ""; + cam1_sync_inverted = [00 00 00 50 73 79 6e 63 2d 67 70 69 6f 73 3a 30 3d 00 00 00 00 07 00 00 00 50 73 79 6e 63 2d 67 70 69 6f 73 3a 34 00 00 00 00 50 73 79 6e 63 2d 67 70 69 6f 73 3a 38 3d 00 00 00 00 01]; + cam0_sync = "", "", "", "Qsync-gpios:0=", "", "", "", "\a", "", "", "Qsync-gpios:4", "", "", "", "Qsync-gpios:8=", "", "", "", ""; + cam0_sync_inverted = [00 00 00 51 73 79 6e 63 2d 67 70 69 6f 73 3a 30 3d 00 00 00 00 07 00 00 00 51 73 79 6e 63 2d 67 70 69 6f 73 3a 34 00 00 00 00 51 73 79 6e 63 2d 67 70 69 6f 73 3a 38 3d 00 00 00 00 01]; + cam0_reg = "", "", "", "Rstatus"; + cam0_reg_gpio = [00 00 00 52 67 70 69 6f 3a 34 00 00 00 00 52 67 70 69 6f 3a 30 3d 00 00 00 00 07]; + cam1_reg = "", "", "", "Sstatus"; + cam1_reg_gpio = [00 00 00 53 67 70 69 6f 3a 34 00 00 00 00 53 67 70 69 6f 3a 30 3d 00 00 00 00 07]; + strict_gpiod = "", "", "", "Tbootargs=pinctrl_bcm2835.persist_gpio_outputs=n"; + arm_freq; + eee = "", "", "", "Tbootargs{on='',off='genet.eee=N'}"; + hdmi = "", "", "", "Ustatus", "", "", "", "Vstatus"; + nvmem_cust_rw = "", "", "", "Wrw?"; + nvmem_priv_rw = "", "", "", "Xrw?"; + pcie = "", "", "", ">status"; + sd = "", "", "", "Ystatus"; + sd_poll_once = "", "", "", "Ynon-removable?"; + spi_dma4 = <0x46 0x646d6173 0x3a303d00 0x2e 0x46 0x646d6173 0x3a383d00 0x2e>; + i2s_dma4 = <0x45 0x646d6173 0x3a303d00 0x2e 0x45 0x646d6173 0x3a383d00 0x2e>; + audio = "", "", "", "Tbootargs{on='snd_bcm2835.enable_headphones=1 snd_bcm2835.enable_hdmi=1',off='snd_bcm2835.enable_headphones=0 snd_bcm2835.enable_hdmi=0'}"; + act_led_gpio = "", "", "", "Zgpios:4"; + act_led_activelow = "", "", "", "Zgpios:8"; + act_led_trigger = "", "", "", "Zlinux,default-trigger"; + pwr_led_gpio = "", "", "", "[gpios:4"; + pwr_led_activelow = "", "", "", "[gpios:8"; + pwr_led_trigger = "", "", "", "[linux,default-trigger"; + eth_led0 = "", "", "", "@led-modes:0"; + eth_led1 = "", "", "", "@led-modes:4"; + }; + + memory@0 { + device_type = "memory"; + reg = <0x00 0x00 0x00>; + }; + + leds { + compatible = "gpio-leds"; + phandle = <0xee>; + + led-act { + label = "ACT"; + default-state = "off"; + linux,default-trigger = "mmc0"; + gpios = <0x07 0x2a 0x00>; + phandle = <0x5a>; + }; + + led-pwr { + label = "PWR"; + gpios = <0x0b 0x02 0x01>; + default-state = "off"; + linux,default-trigger = "default-on"; + phandle = <0x5b>; + }; + }; + + regulator-sd-io-1v8 { + compatible = "regulator-gpio"; + regulator-name = "vdd-sd-io"; + regulator-min-microvolt = <0x1b7740>; + regulator-max-microvolt = <0x325aa0>; + regulator-boot-on; + regulator-always-on; + regulator-settling-time-us = <0x1388>; + gpios = <0x0b 0x04 0x00>; + states = <0x1b7740 0x01 0x325aa0 0x00>; + status = "okay"; + phandle = <0x37>; + }; + + regulator-sd-vcc { + compatible = "regulator-fixed"; + regulator-name = "vcc-sd"; + regulator-min-microvolt = <0x325aa0>; + regulator-max-microvolt = <0x325aa0>; + regulator-boot-on; + enable-active-high; + gpio = <0x0b 0x06 0x00>; + phandle = <0x38>; + }; + + fixedregulator_3v3 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x325aa0>; + regulator-min-microvolt = <0x325aa0>; + regulator-name = "3v3"; + phandle = <0xef>; + }; + + fixedregulator_5v0 { + compatible = "regulator-fixed"; + regulator-always-on; + regulator-max-microvolt = <0x4c4b40>; + regulator-min-microvolt = <0x4c4b40>; + regulator-name = "5v0"; + phandle = <0xf0>; + }; + + zone_dma { + #address-cells = <0x01>; + #size-cells = <0x01>; + dma-ranges = <0x00 0x00 0x00 0x40000000>; + }; + + v3dbus { + compatible = "simple-bus"; + #address-cells = <0x01>; + #size-cells = <0x02>; + ranges = <0x7c500000 0x00 0xfc500000 0x00 0x3300000 0x40000000 0x00 0xff800000 0x00 0x800000>; + dma-ranges = <0x00 0x00 0x00 0x04 0x00>; + phandle = <0xf1>; + + v3d@7ec04000 { + compatible = "brcm,2711-v3d"; + reg = <0x7ec00000 0x00 0x4000 0x7ec04000 0x00 0x4000>; + reg-names = "hub", "core0"; + power-domains = <0x49 0x01>; + resets = <0x49 0x00>; + clocks = <0x14 0x05>; + clocks-names = "v3d"; + interrupts = <0x00 0x4a 0x04>; + status = "disabled"; + phandle = <0xf2>; + }; + }; + + __symbols__ { + aliases = "/aliases"; + chosen = "/chosen"; + rmem = "/reserved-memory"; + cma = "/reserved-memory/linux,cma"; + blconfig = "/reserved-memory/nvram@0"; + blpubkey = "/reserved-memory/nvram@1"; + cpu_thermal = "/thermal-zones/cpu-thermal"; + thermal_trips = "/thermal-zones/cpu-thermal/trips"; + cooling_maps = "/thermal-zones/cpu-thermal/cooling-maps"; + soc = "/soc"; + system_timer = "/soc/timer@7e003000"; + txp = "/soc/txp@7e004000"; + clocks = "/soc/cprman@7e101000"; + mailbox = "/soc/mailbox@7e00b880"; + gpio = "/soc/gpio@7e200000"; + dpi_gpio0 = "/soc/gpio@7e200000/dpi-gpio0"; + emmc_gpio22 = "/soc/gpio@7e200000/emmc-gpio22"; + emmc_gpio34 = "/soc/gpio@7e200000/emmc-gpio34"; + emmc_gpio48 = "/soc/gpio@7e200000/emmc-gpio48"; + gpclk0_gpio4 = "/soc/gpio@7e200000/gpclk0-gpio4"; + gpclk1_gpio5 = "/soc/gpio@7e200000/gpclk1-gpio5"; + gpclk1_gpio42 = "/soc/gpio@7e200000/gpclk1-gpio42"; + gpclk1_gpio44 = "/soc/gpio@7e200000/gpclk1-gpio44"; + gpclk2_gpio6 = "/soc/gpio@7e200000/gpclk2-gpio6"; + gpclk2_gpio43 = "/soc/gpio@7e200000/gpclk2-gpio43"; + i2c0_gpio0 = "/soc/gpio@7e200000/i2c0if-gpio0"; + i2c0_gpio28 = "/soc/gpio@7e200000/i2c0if-gpio28"; + i2c0_gpio44 = "/soc/gpio@7e200000/i2c0if-gpio44"; + i2c1_gpio2 = "/soc/gpio@7e200000/i2c1-gpio2"; + i2c1_gpio44 = "/soc/gpio@7e200000/i2c1-gpio44"; + jtag_gpio22 = "/soc/gpio@7e200000/jtag-gpio22"; + pcm_gpio18 = "/soc/gpio@7e200000/pcm-gpio18"; + pcm_gpio28 = "/soc/gpio@7e200000/pcm-gpio28"; + sdhost_gpio48 = "/soc/gpio@7e200000/sdhost-gpio48"; + spi0_gpio7 = "/soc/gpio@7e200000/spi0-gpio7"; + spi0_gpio35 = "/soc/gpio@7e200000/spi0-gpio35"; + spi1_gpio16 = "/soc/gpio@7e200000/spi1-gpio16"; + spi2_gpio40 = "/soc/gpio@7e200000/spi2-gpio40"; + uart0_gpio14 = "/soc/gpio@7e200000/uart0-gpio14"; + uart0_ctsrts_gpio16 = "/soc/gpio@7e200000/uart0-ctsrts-gpio16"; + uart0_ctsrts_gpio30 = "/soc/gpio@7e200000/uart0-ctsrts-gpio30"; + uart0_gpio32 = "/soc/gpio@7e200000/uart0-gpio32"; + uart0_gpio36 = "/soc/gpio@7e200000/uart0-gpio36"; + uart0_ctsrts_gpio38 = "/soc/gpio@7e200000/uart0-ctsrts-gpio38"; + uart1_gpio14 = "/soc/gpio@7e200000/uart1-gpio14"; + uart1_ctsrts_gpio16 = "/soc/gpio@7e200000/uart1-ctsrts-gpio16"; + uart1_gpio32 = "/soc/gpio@7e200000/uart1-gpio32"; + uart1_ctsrts_gpio30 = "/soc/gpio@7e200000/uart1-ctsrts-gpio30"; + uart1_gpio40 = "/soc/gpio@7e200000/uart1-gpio40"; + uart1_ctsrts_gpio42 = "/soc/gpio@7e200000/uart1-ctsrts-gpio42"; + gpclk0_gpio49 = "/soc/gpio@7e200000/gpclk0-gpio49"; + gpclk1_gpio50 = "/soc/gpio@7e200000/gpclk1-gpio50"; + gpclk2_gpio51 = "/soc/gpio@7e200000/gpclk2-gpio51"; + i2c0_gpio46 = "/soc/gpio@7e200000/i2c0if-gpio46"; + i2c1_gpio46 = "/soc/gpio@7e200000/i2c1-gpio46"; + i2c3_gpio2 = "/soc/gpio@7e200000/i2c3-gpio2"; + i2c3_gpio4 = "/soc/gpio@7e200000/i2c3-gpio4"; + i2c4_gpio6 = "/soc/gpio@7e200000/i2c4-gpio6"; + i2c4_gpio8 = "/soc/gpio@7e200000/i2c4-gpio8"; + i2c5_gpio10 = "/soc/gpio@7e200000/i2c5-gpio10"; + i2c5_gpio12 = "/soc/gpio@7e200000/i2c5-gpio12"; + i2c6_gpio0 = "/soc/gpio@7e200000/i2c6-gpio0"; + i2c6_gpio22 = "/soc/gpio@7e200000/i2c6-gpio22"; + i2c_slave_gpio8 = "/soc/gpio@7e200000/i2c-slave-gpio8"; + jtag_gpio48 = "/soc/gpio@7e200000/jtag-gpio48"; + mii_gpio28 = "/soc/gpio@7e200000/mii-gpio28"; + mii_gpio36 = "/soc/gpio@7e200000/mii-gpio36"; + pcm_gpio50 = "/soc/gpio@7e200000/pcm-gpio50"; + pwm0_0_gpio12 = "/soc/gpio@7e200000/pwm0-0-gpio12"; + pwm0_0_gpio18 = "/soc/gpio@7e200000/pwm0-0-gpio18"; + pwm1_0_gpio40 = "/soc/gpio@7e200000/pwm1-0-gpio40"; + pwm0_1_gpio13 = "/soc/gpio@7e200000/pwm0-1-gpio13"; + pwm0_1_gpio19 = "/soc/gpio@7e200000/pwm0-1-gpio19"; + pwm1_1_gpio41 = "/soc/gpio@7e200000/pwm1-1-gpio41"; + pwm0_1_gpio45 = "/soc/gpio@7e200000/pwm0-1-gpio45"; + pwm0_0_gpio52 = "/soc/gpio@7e200000/pwm0-0-gpio52"; + pwm0_1_gpio53 = "/soc/gpio@7e200000/pwm0-1-gpio53"; + rgmii_gpio35 = "/soc/gpio@7e200000/rgmii-gpio35"; + rgmii_irq_gpio34 = "/soc/gpio@7e200000/rgmii-irq-gpio34"; + rgmii_irq_gpio39 = "/soc/gpio@7e200000/rgmii-irq-gpio39"; + rgmii_mdio_gpio28 = "/soc/gpio@7e200000/rgmii-mdio-gpio28"; + rgmii_mdio_gpio37 = "/soc/gpio@7e200000/rgmii-mdio-gpio37"; + spi0_gpio46 = "/soc/gpio@7e200000/spi0-gpio46"; + spi2_gpio46 = "/soc/gpio@7e200000/spi2-gpio46"; + spi3_gpio0 = "/soc/gpio@7e200000/spi3-gpio0"; + spi4_gpio4 = "/soc/gpio@7e200000/spi4-gpio4"; + spi5_gpio12 = "/soc/gpio@7e200000/spi5-gpio12"; + spi6_gpio18 = "/soc/gpio@7e200000/spi6-gpio18"; + uart2_gpio0 = "/soc/gpio@7e200000/uart2-gpio0"; + uart2_ctsrts_gpio2 = "/soc/gpio@7e200000/uart2-ctsrts-gpio2"; + uart3_gpio4 = "/soc/gpio@7e200000/uart3-gpio4"; + uart3_ctsrts_gpio6 = "/soc/gpio@7e200000/uart3-ctsrts-gpio6"; + uart4_gpio8 = "/soc/gpio@7e200000/uart4-gpio8"; + uart4_ctsrts_gpio10 = "/soc/gpio@7e200000/uart4-ctsrts-gpio10"; + uart5_gpio12 = "/soc/gpio@7e200000/uart5-gpio12"; + uart5_ctsrts_gpio14 = "/soc/gpio@7e200000/uart5-ctsrts-gpio14"; + dpi_18bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio0"; + dpi_18bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_18bit_cpadhi_gpio2"; + dpi_18bit_gpio0 = "/soc/gpio@7e200000/dpi_18bit_gpio0"; + dpi_18bit_gpio2 = "/soc/gpio@7e200000/dpi_18bit_gpio2"; + dpi_16bit_gpio0 = "/soc/gpio@7e200000/dpi_16bit_gpio0"; + dpi_16bit_gpio2 = "/soc/gpio@7e200000/dpi_16bit_gpio2"; + dpi_16bit_cpadhi_gpio0 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio0"; + dpi_16bit_cpadhi_gpio2 = "/soc/gpio@7e200000/dpi_16bit_cpadhi_gpio2"; + gpioout = "/soc/gpio@7e200000/gpioout"; + alt0 = "/soc/gpio@7e200000/alt0"; + spi0_pins = "/soc/gpio@7e200000/spi0_pins"; + spi0_cs_pins = "/soc/gpio@7e200000/spi0_cs_pins"; + spi3_pins = "/soc/gpio@7e200000/spi3_pins"; + spi3_cs_pins = "/soc/gpio@7e200000/spi3_cs_pins"; + spi4_pins = "/soc/gpio@7e200000/spi4_pins"; + spi4_cs_pins = "/soc/gpio@7e200000/spi4_cs_pins"; + spi5_pins = "/soc/gpio@7e200000/spi5_pins"; + spi5_cs_pins = "/soc/gpio@7e200000/spi5_cs_pins"; + spi6_pins = "/soc/gpio@7e200000/spi6_pins"; + spi6_cs_pins = "/soc/gpio@7e200000/spi6_cs_pins"; + i2c0_pins = "/soc/gpio@7e200000/i2c0"; + i2c1_pins = "/soc/gpio@7e200000/i2c1"; + i2c3_pins = "/soc/gpio@7e200000/i2c3"; + i2c4_pins = "/soc/gpio@7e200000/i2c4"; + i2c5_pins = "/soc/gpio@7e200000/i2c5"; + i2c6_pins = "/soc/gpio@7e200000/i2c6"; + i2s_pins = "/soc/gpio@7e200000/i2s"; + sdio_pins = "/soc/gpio@7e200000/sdio_pins"; + uart2_pins = "/soc/gpio@7e200000/uart2_pins"; + uart3_pins = "/soc/gpio@7e200000/uart3_pins"; + uart4_pins = "/soc/gpio@7e200000/uart4_pins"; + uart5_pins = "/soc/gpio@7e200000/uart5_pins"; + bt_pins = "/soc/gpio@7e200000/bt_pins"; + uart0_pins = "/soc/gpio@7e200000/uart0_pins"; + uart1_pins = "/soc/gpio@7e200000/uart1_pins"; + uart1_bt_pins = "/soc/gpio@7e200000/uart1_bt_pins"; + audio_pins = "/soc/gpio@7e200000/audio_pins"; + uart0 = "/soc/serial@7e201000"; + bt = "/soc/serial@7e201000/bluetooth"; + sdhost = "/soc/mmc@7e202000"; + i2s_clk_consumer = "/soc/i2s@7e203000"; + i2s_clk_producer = "/soc/i2s@7e203000"; + i2s = "/soc/i2s@7e203000"; + spi0 = "/soc/spi@7e204000"; + spi = "/soc/spi@7e204000"; + spidev0 = "/soc/spi@7e204000/spidev@0"; + spidev1 = "/soc/spi@7e204000/spidev@1"; + i2c0if = "/soc/i2c@7e205000"; + dpi = "/soc/dpi@7e208000"; + dsi0 = "/soc/dsi@7e209000"; + aux = "/soc/aux@7e215000"; + uart1 = "/soc/serial@7e215040"; + minibt = "/soc/serial@7e215040/bluetooth"; + spi1 = "/soc/spi@7e215080"; + spi2 = "/soc/spi@7e2150c0"; + pwm = "/soc/pwm@7e20c000"; + mmc = "/soc/mmc@7e300000"; + sdhci = "/soc/mmc@7e300000"; + hvs = "/soc/hvs@7e400000"; + dsi1 = "/soc/dsi@7e700000"; + i2c_arm = "/soc/i2c@7e804000"; + i2c1 = "/soc/i2c@7e804000"; + usb = "/soc/usb@7e980000"; + local_intc = "/soc/interrupt-controller@40000000"; + gicv2 = "/soc/interrupt-controller@40041000"; + avs_monitor = "/soc/avs-monitor@7d5d2000"; + thermal = "/soc/avs-monitor@7d5d2000/thermal"; + dma = "/soc/dma-controller@7e007000"; + watchdog = "/soc/watchdog@7e100000"; + pm = "/soc/watchdog@7e100000"; + random = "/soc/rng@7e104000"; + uart2 = "/soc/serial@7e201400"; + uart3 = "/soc/serial@7e201600"; + uart4 = "/soc/serial@7e201800"; + uart5 = "/soc/serial@7e201a00"; + spi3 = "/soc/spi@7e204600"; + spi4 = "/soc/spi@7e204800"; + spi5 = "/soc/spi@7e204a00"; + spi6 = "/soc/spi@7e204c00"; + i2c3 = "/soc/i2c@7e205600"; + i2c4 = "/soc/i2c@7e205800"; + i2c5 = "/soc/i2c@7e205a00"; + i2c6 = "/soc/i2c@7e205c00"; + pixelvalve0 = "/soc/pixelvalve@7e206000"; + pixelvalve1 = "/soc/pixelvalve@7e207000"; + pixelvalve2 = "/soc/pixelvalve@7e20a000"; + pwm1 = "/soc/pwm@7e20c800"; + pixelvalve4 = "/soc/pixelvalve@7e216000"; + pixelvalve3 = "/soc/pixelvalve@7ec12000"; + vec = "/soc/vec@7ec13000"; + dvp = "/soc/clock@7ef00000"; + aon_intr = "/soc/interrupt-controller@7ef00100"; + hdmi0 = "/soc/hdmi@7ef00700"; + ddc0 = "/soc/i2c@7ef04500"; + hdmi1 = "/soc/hdmi@7ef05700"; + ddc1 = "/soc/i2c@7ef09500"; + mmcnr = "/soc/mmcnr@7e300000"; + firmwarekms = "/soc/firmwarekms@7e600000"; + smi = "/soc/smi@7e600000"; + csi0 = "/soc/csi@7e800000"; + csi1 = "/soc/csi@7e801000"; + axiperf = "/soc/axiperf"; + i2c0mux = "/soc/i2c0mux"; + i2c_csi_dsi0 = "/soc/i2c0mux/i2c@0"; + i2c_vc = "/soc/i2c0mux/i2c@0"; + i2c0 = "/soc/i2c0mux/i2c@0"; + i2c_csi_dsi = "/soc/i2c0mux/i2c@1"; + firmware = "/soc/firmware"; + firmware_clocks = "/soc/firmware/clocks"; + expgpio = "/soc/firmware/gpio"; + reset = "/soc/firmware/reset"; + vcio = "/soc/firmware/vcio"; + power = "/soc/power"; + vchiq = "/soc/mailbox@7e00b840"; + fb = "/soc/fb"; + sound = "/soc/sound"; + nvmem_otp = "/soc/nvmem/nvmem_otp"; + nvmem_cust = "/soc/nvmem/nvmem_cust"; + nvmem_priv = "/soc/nvmem/nvmem_priv"; + clk_osc = "/clocks/clk-osc"; + clk_usb = "/clocks/clk-usb"; + usbphy = "/phy"; + vc4 = "/gpu"; + clk_27MHz = "/clk-27M"; + clk_108MHz = "/clk-108M"; + emmc2bus = "/emmc2bus"; + emmc2 = "/emmc2bus/mmc@7e340000"; + cpus = "/cpus"; + cpu0 = "/cpus/cpu@0"; + cpu1 = "/cpus/cpu@1"; + cpu2 = "/cpus/cpu@2"; + cpu3 = "/cpus/cpu@3"; + l2 = "/cpus/l2-cache0"; + scb = "/scb"; + pcie0 = "/scb/pcie@7d500000"; + genet = "/scb/ethernet@7d580000"; + genet_mdio = "/scb/ethernet@7d580000/mdio@e14"; + phy1 = "/scb/ethernet@7d580000/mdio@e14/ethernet-phy@1"; + dma40 = "/scb/dma@7e007b00"; + xhci = "/scb/xhci@7e9c0000"; + cam1_reg = "/cam1_regulator"; + cam1_clk = "/cam1_clk"; + cam0_regulator = "/cam0_regulator"; + cam0_clk = "/cam0_clk"; + cam0_reg = "/cam_dummy_reg"; + cam_dummy_reg = "/cam_dummy_reg"; + leds = "/leds"; + led_act = "/leds/led-act"; + led_pwr = "/leds/led-pwr"; + sd_io_1v8_reg = "/regulator-sd-io-1v8"; + sd_vcc_reg = "/regulator-sd-vcc"; + vdd_3v3_reg = "/fixedregulator_3v3"; + vdd_5v0_reg = "/fixedregulator_5v0"; + v3dbus = "/v3dbus"; + v3d = "/v3dbus/v3d@7ec04000"; + }; +}; diff --git a/etc/ld/aarch64-unknown-none.ld b/etc/ld/aarch64-unknown-none.ld new file mode 100644 index 00000000..8bb43d8a --- /dev/null +++ b/etc/ld/aarch64-unknown-none.ld @@ -0,0 +1,75 @@ +ENTRY(__aarch64_entry); + +SECTIONS { + . = 0x0; + + PROVIDE(__kernel_start = .); + + .text : { + *(.text.entry) + *(.text*) + } + + . = ALIGN(4K); + + .rodata : { + *(.rodata*) + *(.eh_frame*) + + . = ALIGN(16); + PROVIDE(__init_array_start = .); + KEEP(*(.init_array*)); + PROVIDE(__init_array_end = .); + } + + . = ALIGN(4K); + + .rela : { + PROVIDE(__rela_start = .); + *(.rela*) + PROVIDE(__rela_end = .); + } + + .got : { + *(.got*) + } + + .dynamic : { + *(.dynamic) + } + + . = ALIGN(4K); + + .data : { + *(.data*) + } + + . = ALIGN(4K); + PROVIDE(__bss_start = .); + + .bss : { + *(COMMON) + *(.bss*) + } + + . = ALIGN(4K); + PROVIDE(__bss_end = .); + PROVIDE(__kernel_end = .); + PROVIDE(__kernel_size = __kernel_end - __kernel_start); + + .dynsym : { + *(.dynsym) + } + + .gnu.hash : { + *(.gnu.hash) + } + + .hash : { + *(.hash) + } + + .dynstr : { + *(.dynstr) + } +} diff --git a/etc/ld/arm/aarch64-unknown-qemu.ld b/etc/ld/arm/aarch64-unknown-qemu.ld deleted file mode 100644 index b658c559..00000000 --- a/etc/ld/arm/aarch64-unknown-qemu.ld +++ /dev/null @@ -1,56 +0,0 @@ -ENTRY(__aarch64_entry); - -KERNEL_PHYS_BASE = 0x40200000; -KERNEL_VIRT_OFFSET = 0xFFFFFF8000000000; - -SECTIONS { - . = KERNEL_PHYS_BASE; - PROVIDE(__kernel_start = . + KERNEL_VIRT_OFFSET); - - .text.entry : { - *(.text.entry) - } - - . = ALIGN(16); - . = . + KERNEL_VIRT_OFFSET; - - .text : AT(. - KERNEL_VIRT_OFFSET) { - KEEP(*(.text.vectors)); - *(.text*) - } - - . = ALIGN(4K); - .rodata : AT(. - KERNEL_VIRT_OFFSET) { - *(.rodata*) - *(.eh_frame*) - - . = ALIGN(16); - PROVIDE(__init_array_start = .); - KEEP(*(.init_array*)) - PROVIDE(__init_array_end = .); - } - - . = ALIGN(4K); - .data.tables : AT (. - KERNEL_VIRT_OFFSET) { - KEEP(*(.data.tables)) - } - - . = ALIGN(4K); - .data : AT(. - KERNEL_VIRT_OFFSET) { - *(.data*) - *(.got*) - } - - . = ALIGN(4K); - PROVIDE(__bss_start_phys = . - KERNEL_VIRT_OFFSET); - .bss : AT(. - KERNEL_VIRT_OFFSET) { - *(COMMON) - *(.bss*) - } - . = ALIGN(4K); - PROVIDE(__bss_end_phys = . - KERNEL_VIRT_OFFSET); - PROVIDE(__bss_size = __bss_end_phys - __bss_start_phys); - - PROVIDE(__kernel_end = .); - PROVIDE(__kernel_size = __kernel_end - __kernel_start); -}; diff --git a/etc/ld/arm/aarch64-unknown-raspi4b.ld b/etc/ld/arm/aarch64-unknown-raspi4b.ld deleted file mode 100644 index b16e11e8..00000000 --- a/etc/ld/arm/aarch64-unknown-raspi4b.ld +++ /dev/null @@ -1,56 +0,0 @@ -ENTRY(__aarch64_entry); - -KERNEL_PHYS_BASE = 0x200000; -KERNEL_VIRT_OFFSET = 0xFFFFFF8000000000; - -SECTIONS { - . = KERNEL_PHYS_BASE; - PROVIDE(__kernel_start = . + KERNEL_VIRT_OFFSET); - - .text.entry : { - *(.text.entry) - } - - . = ALIGN(16); - . = . + KERNEL_VIRT_OFFSET; - - .text : AT(. - KERNEL_VIRT_OFFSET) { - KEEP(*(.text.vectors)); - *(.text*) - } - - . = ALIGN(4K); - .rodata : AT(. - KERNEL_VIRT_OFFSET) { - *(.rodata*) - *(.eh_frame*) - - . = ALIGN(16); - PROVIDE(__init_array_start = .); - KEEP(*(.init_array*)) - PROVIDE(__init_array_end = .); - } - - . = ALIGN(4K); - .data.tables : AT (. - KERNEL_VIRT_OFFSET) { - KEEP(*(.data.tables)) - } - - . = ALIGN(4K); - .data : AT(. - KERNEL_VIRT_OFFSET) { - *(.data*) - *(.got*) - } - - . = ALIGN(4K); - PROVIDE(__bss_start_phys = . - KERNEL_VIRT_OFFSET); - .bss : AT(. - KERNEL_VIRT_OFFSET) { - *(COMMON) - *(.bss*) - } - . = ALIGN(4K); - PROVIDE(__bss_end_phys = . - KERNEL_VIRT_OFFSET); - PROVIDE(__bss_size = __bss_end_phys - __bss_start_phys); - - PROVIDE(__kernel_end = .); - PROVIDE(__kernel_size = __kernel_end - __kernel_start); -}; diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 3436da46..27169af0 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -94,12 +94,5 @@ ygg_driver_net_stmmac.path = "driver/net/stmmac" default = ["fb_console"] fb_console = [] -# TODO replace this with a better configuration mechanism -aarch64_board_virt = ["kernel-arch-aarch64/aarch64_board_virt"] -aarch64_board_raspi4b = ["kernel-arch-aarch64/aarch64_board_raspi4b"] - -riscv64_board_virt = ["kernel-arch-riscv64/riscv64_board_virt"] -riscv64_board_jh7110 = ["kernel-arch-riscv64/riscv64_board_jh7110"] - [lints] workspace = true diff --git a/kernel/arch/aarch64/Cargo.toml b/kernel/arch/aarch64/Cargo.toml index 0a456482..e50e1c3a 100644 --- a/kernel/arch/aarch64/Cargo.toml +++ b/kernel/arch/aarch64/Cargo.toml @@ -18,10 +18,5 @@ tock-registers.workspace = true [build-dependencies] cc = "1.0" -[features] -default = [] -aarch64_board_virt = [] -aarch64_board_raspi4b = [] - [lints] workspace = true diff --git a/kernel/arch/aarch64/src/mem/fixed.rs b/kernel/arch/aarch64/src/mem/fixed.rs new file mode 100644 index 00000000..fbeef509 --- /dev/null +++ b/kernel/arch/aarch64/src/mem/fixed.rs @@ -0,0 +1,121 @@ +use core::ops::Range; + +use aarch64_cpu::registers::{TTBR0_EL1, TTBR1_EL1}; +use kernel_arch_interface::{mem::DeviceMemoryAttributes, KERNEL_VIRT_OFFSET}; +use libk_mm_interface::{ + address::PhysicalAddress, + device::{DevicePageManager, DevicePageTableLevel}, + table::EntryLevel, +}; + +use crate::mem::{ + auto_lower_address, + table::{PageAttributes, PageEntry, PageTable, L1, L2, L3}, + tlb_flush_range_va, +}; + +pub const IDENTITY_SIZE_L1: usize = 8; +pub const DEVICE_L1: usize = IDENTITY_SIZE_L1; +pub const DEVICE_MAPPING_L3_COUNT: usize = 32; +pub const DEVICE_MAPPING_OFFSET: usize = KERNEL_VIRT_OFFSET + (DEVICE_L1 << L1::SHIFT); + +#[repr(transparent)] +pub struct L2DeviceMemory(pub PageTable); +#[repr(transparent)] +pub struct L3DeviceMemory(pub [PageTable; DEVICE_MAPPING_L3_COUNT]); + +static mut KERNEL_L1: PageTable = PageTable::zeroed(); +pub(super) static mut DEVICE_MEMORY: DevicePageManager = + DevicePageManager::new( + L3DeviceMemory([PageTable::zeroed(); DEVICE_MAPPING_L3_COUNT]), + L2DeviceMemory(PageTable::zeroed()), + ); + +impl DevicePageTableLevel for L2DeviceMemory { + type Level = L2; + const VIRTUAL_BASE: usize = DEVICE_MAPPING_OFFSET; + const INDEX_RANGE: Range = DEVICE_MAPPING_L3_COUNT..512; + + fn map_page( + &mut self, + index: usize, + physical: PhysicalAddress, + attrs: &DeviceMemoryAttributes, + ) { + loop {} + } + + fn unmap_page(&mut self, index: usize) { + loop {} + } + + fn is_mapped(&self, index: usize) -> bool { + loop {} + } + + fn flush_range(range: Range) { + loop {} + } +} + +impl DevicePageTableLevel for L3DeviceMemory { + type Level = L3; + const VIRTUAL_BASE: usize = DEVICE_MAPPING_OFFSET; + const INDEX_RANGE: Range = 0..512 * DEVICE_MAPPING_L3_COUNT; + + fn map_page( + &mut self, + index: usize, + physical: PhysicalAddress, + attrs: &DeviceMemoryAttributes, + ) { + let _ = attrs; + let l2i = index / 512; + let l3i = index % 512; + self.0[l2i][l3i] = PageEntry::device_page(physical); + } + + fn unmap_page(&mut self, index: usize) { + let l2i = index / 512; + let l3i = index % 512; + self.0[l2i][l3i] = PageEntry::INVALID; + } + + fn is_mapped(&self, index: usize) -> bool { + let l2i = index / 512; + let l3i = index % 512; + self.0[l2i][l3i].is_present() + } + + fn flush_range(range: Range) { + let start = range.start * L3::SIZE + Self::VIRTUAL_BASE; + let size = (range.end - range.start) * L3::SIZE; + tlb_flush_range_va(start, size); + } +} + +pub unsafe fn setup() { + // 0..IDENTITY_SIZE_L1 -> lower RAM region + for i in 0..IDENTITY_SIZE_L1 { + let phys = PhysicalAddress::from_usize(i << L1::SHIFT); + KERNEL_L1[i] = PageEntry::normal_block(phys, PageAttributes::empty()); + } + + // DEVICE_L1 -> Device L2 table + // 0..DEVICE_MAPPING_L3_COUNT -> Device L3 tables -> Device L3 pages + // ..512 -> Device L2 pages + for i in 0..DEVICE_MAPPING_L3_COUNT { + let phys = + PhysicalAddress::from_usize(auto_lower_address(&raw const DEVICE_MEMORY.normal.0[i])); + DEVICE_MEMORY.large.0[i] = PageEntry::table(phys, PageAttributes::empty()); + } + let phys = PhysicalAddress::from_usize(auto_lower_address(&raw const DEVICE_MEMORY.large.0)); + KERNEL_L1[DEVICE_L1] = PageEntry::table(phys, PageAttributes::empty()); +} + +pub unsafe fn load() { + let ttbr_physical = auto_lower_address(&raw const KERNEL_L1) as u64; + + TTBR0_EL1.set_baddr(ttbr_physical); + TTBR1_EL1.set_baddr(ttbr_physical); +} diff --git a/kernel/arch/aarch64/src/mem/intrinsics.rs b/kernel/arch/aarch64/src/mem/intrinsics.rs new file mode 100644 index 00000000..0fd00479 --- /dev/null +++ b/kernel/arch/aarch64/src/mem/intrinsics.rs @@ -0,0 +1,144 @@ +use core::{ + ops::Range, + sync::atomic::{self, Ordering}, +}; + +use aarch64_cpu::{ + asm::barrier, + registers::{PAR_EL1, SCTLR_EL1}, +}; +use libk_mm_interface::table::{EntryLevel, EntryLevelExt}; +use tock_registers::interfaces::{ReadWriteable, Readable}; + +use crate::mem::table::L3; + +/// Enables data cache. +/// +/// # Safety +/// +/// Manipulates low-level machine state, use with care. +pub unsafe fn enable_dcache() { + barrier::dsb(barrier::ISHST); + barrier::isb(barrier::SY); + + SCTLR_EL1.modify(SCTLR_EL1::C::Cacheable); + + barrier::dsb(barrier::ISH); + barrier::isb(barrier::SY); +} + +/// Enables instruction cache. +/// +/// # Safety +/// +/// Manipulates low-level machine state, use with care. +pub unsafe fn enable_icache() { + barrier::isb(barrier::SY); + + SCTLR_EL1.modify(SCTLR_EL1::I::Cacheable); + + barrier::dsb(barrier::ISH); + barrier::isb(barrier::SY); +} + +/// Disables instruction cache. +/// +/// # Safety +/// +/// Manipulates low-level machine state, use with care. Might break some instructions. +pub unsafe fn disable_icache() { + barrier::isb(barrier::SY); + + ic_iallu(); + SCTLR_EL1.modify(SCTLR_EL1::I::NonCacheable); + + barrier::dsb(barrier::ISH); + barrier::isb(barrier::SY); +} + +#[inline] +pub fn tlb_flush_asid(asid: u8) { + barrier::dsb(barrier::ISHST); + let value = (asid as u64) << 48; + unsafe { + core::arch::asm!("tlbi aside1, {value}", value = in(reg) value); + } + barrier::dsb(barrier::ISH); + barrier::isb(barrier::SY); +} + +#[inline] +pub fn tlb_flush_all() { + barrier::dsb(barrier::ISHST); + unsafe { + core::arch::asm!("tlbi vmalle1is"); + } + barrier::dsb(barrier::ISH); + barrier::isb(barrier::SY); +} + +#[inline] +pub fn tlb_flush_vaae1(page: usize) { + barrier::dsb(barrier::ISHST); + let argument = page >> 12; + unsafe { + core::arch::asm!("tlbi vaae1, {argument}", argument = in(reg) argument); + } + barrier::dsb(barrier::ISH); + barrier::isb(barrier::SY); +} + +#[inline] +pub fn tlb_flush_range_va(base: usize, size: usize) { + let end = (base + size).page_align_up::(); + let base = base.page_align_down::(); + let count = (end - base).page_count::(); + for i in 0..count { + tlb_flush_vaae1(base + i * L3::SIZE); + } +} + +pub fn at_s1e0r(input: usize) -> Option { + barrier::dsb(barrier::ISHST); + unsafe { + core::arch::asm!("at s1e0r, {address}", address = in(reg) input); + } + barrier::dsb(barrier::ISH); + barrier::isb(barrier::SY); + if PAR_EL1.matches_all(PAR_EL1::F::TranslationSuccessfull) { + Some(PAR_EL1.read(PAR_EL1::PA)) + } else { + None + } +} + +pub fn at_s1e1r(input: usize) -> Option { + barrier::dsb(barrier::ISHST); + unsafe { + core::arch::asm!("at s1e1r, {address}", address = in(reg) input); + } + barrier::dsb(barrier::ISH); + barrier::isb(barrier::SY); + if PAR_EL1.matches_all(PAR_EL1::F::TranslationSuccessfull) { + Some(PAR_EL1.read(PAR_EL1::PA)) + } else { + None + } +} + +pub fn ic_iallu() { + atomic::compiler_fence(Ordering::SeqCst); + barrier::dsb(barrier::ISH); + barrier::isb(barrier::SY); + unsafe { + core::arch::asm!("ic iallu"); + } + barrier::isb(barrier::SY); +} + +pub fn dc_cvac(input: usize) { + barrier::dsb(barrier::ISHST); + unsafe { + core::arch::asm!("dc cvac, {address}", address = in(reg) input); + } +} diff --git a/kernel/arch/aarch64/src/mem/mod.rs b/kernel/arch/aarch64/src/mem/mod.rs index 578160bf..465734ce 100644 --- a/kernel/arch/aarch64/src/mem/mod.rs +++ b/kernel/arch/aarch64/src/mem/mod.rs @@ -1,108 +1,48 @@ -use core::{ - alloc::Layout, - ops::{Deref, DerefMut}, - sync::atomic::{self, AtomicUsize, Ordering}, -}; - use aarch64_cpu::{ asm::barrier, - registers::{MAIR_EL1, PAR_EL1, SCTLR_EL1, TTBR0_EL1, TTBR1_EL1}, + registers::{MAIR_EL1, SCTLR_EL1, TCR_EL1}, }; use kernel_arch_interface::{ mem::{DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping}, - split_spinlock, Architecture, KERNEL_VIRT_OFFSET, + sync::IrqSafeSpinlock, + KERNEL_VIRT_OFFSET, }; -use libk_mm_interface::{ - address::PhysicalAddress, - table::{page_index, EntryLevel, EntryLevelExt}, -}; -use memtables::aarch64::{FixedTables, KERNEL_L3_COUNT}; -use static_assertions::const_assert_eq; -use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; +use libk_mm_interface::{address::PhysicalAddress, table::EntryLevel}; +use tock_registers::interfaces::{ReadWriteable, Writeable}; use yggdrasil_abi::error::Error; -use crate::ArchitectureImpl; +pub use intrinsics::*; -use self::table::{PageAttributes, PageEntry, PageTable, L1, L2, L3}; +use crate::{mem::table::L1, ArchitectureImpl}; +pub mod fixed; +pub mod intrinsics; pub mod process; pub mod table; #[derive(Debug)] pub struct KernelTableManagerImpl; -// TODO eliminate this requirement by using precomputed indices -const MAPPING_OFFSET: usize = KERNEL_VIRT_OFFSET; - -#[cfg(any(feature = "aarch64_board_virt", rust_analyzer))] -const KERNEL_PHYS_BASE: usize = 0x40200000; -#[cfg(any(feature = "aarch64_board_raspi4b", rust_analyzer))] -const KERNEL_PHYS_BASE: usize = 0x200000; - -// Precomputed mappings -const KERNEL_L1_INDEX: usize = page_index::(KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE); -const KERNEL_START_L2_INDEX: usize = page_index::(KERNEL_VIRT_OFFSET + KERNEL_PHYS_BASE); -const KERNEL_END_L2_INDEX: usize = KERNEL_START_L2_INDEX + KERNEL_L3_COUNT; - -// Must not be zero, should be at 4MiB -// const_assert_eq!(KERNEL_START_L2_INDEX, 0); -// From static mapping -#[cfg(any(feature = "aarch64_board_raspi4b", rust_analyzer))] -const_assert_eq!(KERNEL_L1_INDEX, 0); -#[cfg(any(feature = "aarch64_board_virt", rust_analyzer))] -const_assert_eq!(KERNEL_L1_INDEX, 1); - -// Runtime mappings -// 2MiB max -const EARLY_MAPPING_L2I: usize = KERNEL_END_L2_INDEX + 1; -// 1GiB max -const DEVICE_MAPPING_L1I: usize = KERNEL_L1_INDEX + 2; -const DEVICE_MAPPING_L3_COUNT: usize = 4; -// 16GiB max -const RAM_MAPPING_START_L1I: usize = KERNEL_L1_INDEX + 3; -pub const RAM_MAPPING_L1_COUNT: usize = 16; - -// 2MiB for early mappings -const EARLY_MAPPING_OFFSET: usize = - MAPPING_OFFSET | (KERNEL_L1_INDEX * L1::SIZE) | (EARLY_MAPPING_L2I * L2::SIZE); -static mut EARLY_MAPPING_L3: PageTable = PageTable::zeroed(); -// 1GiB for device MMIO mapping -const DEVICE_MAPPING_OFFSET: usize = MAPPING_OFFSET | (DEVICE_MAPPING_L1I * L1::SIZE); -static mut DEVICE_MAPPING_L2: PageTable = PageTable::zeroed(); -static mut DEVICE_MAPPING_L3S: [PageTable; DEVICE_MAPPING_L3_COUNT] = - [PageTable::zeroed(); DEVICE_MAPPING_L3_COUNT]; -// 16GiB for RAM mapping -pub const RAM_MAPPING_OFFSET: usize = MAPPING_OFFSET | (RAM_MAPPING_START_L1I * L1::SIZE); -pub static MEMORY_LIMIT: AtomicUsize = AtomicUsize::new(0); - -split_spinlock! { - use crate::ArchitectureImpl; - use crate::mem::FixedTables; - use libk_mm_interface::KernelImageObject; - - #[link_section = ".data.tables"] - static KERNEL_TABLES: KernelImageObject = - unsafe { KernelImageObject::new(FixedTables::zeroed()) }; -} +static KERNEL_MEMORY_LOCK: IrqSafeSpinlock = IrqSafeSpinlock::new(()); impl KernelTableManager for KernelTableManagerImpl { fn virtualize(address: u64) -> usize { let address = address as usize; - if address < MEMORY_LIMIT.load(Ordering::Acquire) { - address + RAM_MAPPING_OFFSET + if address < fixed::IDENTITY_SIZE_L1 * L1::SIZE { + address + KERNEL_VIRT_OFFSET } else { - panic!("Invalid physical address: {:#x}", address); + panic!("Invalid physical address: {address:#x}"); } } fn physicalize(address: usize) -> u64 { - if address < RAM_MAPPING_OFFSET - || address - RAM_MAPPING_OFFSET >= MEMORY_LIMIT.load(Ordering::Acquire) + if address < KERNEL_VIRT_OFFSET + || address - KERNEL_VIRT_OFFSET >= fixed::IDENTITY_SIZE_L1 * L1::SIZE { - panic!("Not a virtualized physical address: {:#x}", address); + panic!("Invalid virtual (-> physical) address {address:#x}"); } - (address - RAM_MAPPING_OFFSET) as _ + (address - KERNEL_VIRT_OFFSET) as u64 } unsafe fn map_device_pages( @@ -110,442 +50,94 @@ impl KernelTableManager for KernelTableManagerImpl { count: usize, attrs: DeviceMemoryAttributes, ) -> Result, Error> { - map_device_memory(PhysicalAddress::from_u64(base), count, attrs) + let _lock = KERNEL_MEMORY_LOCK.lock(); + fixed::DEVICE_MEMORY.map_device_pages(PhysicalAddress::from_u64(base), count, attrs) } unsafe fn unmap_device_pages(mapping: &RawDeviceMemoryMapping) { - unmap_device_memory(mapping) - } -} - -/// Memory mapping which may be used for performing early kernel initialization -pub struct EarlyMapping<'a, T: ?Sized> { - value: &'a mut T, - page_count: usize, -} - -impl<'a, T: Sized> EarlyMapping<'a, T> { - /// # Safety - /// - /// `physical` address provided must be a valid non-NULL address actually containing `T`. - pub unsafe fn map_slice( - physical: PhysicalAddress, - len: usize, - ) -> Result, Error> { - let layout = Layout::array::(len).unwrap(); - let aligned = physical.page_align_down::(); - let offset = physical.page_offset::(); - let page_count = (offset + layout.size()).div_ceil(L3::SIZE); - - let virt = map_early_pages(aligned, page_count)?; - let value = core::slice::from_raw_parts_mut((virt + offset) as *mut T, len); - - Ok(EarlyMapping { value, page_count }) - } -} - -impl Deref for EarlyMapping<'_, T> { - type Target = T; - - fn deref(&self) -> &Self::Target { - self.value - } -} - -impl DerefMut for EarlyMapping<'_, T> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.value - } -} - -impl Drop for EarlyMapping<'_, T> { - fn drop(&mut self) { - let address = (self.value as *mut T).addr() & !(L3::SIZE - 1); - - for i in 0..self.page_count { - let page = address + i * L3::SIZE; - - unsafe { - unmap_early_page(page); - } - } - } -} - -fn kernel_table_flags() -> PageAttributes { - PageAttributes::TABLE - | PageAttributes::ACCESS - | PageAttributes::SH_INNER - | PageAttributes::PAGE_ATTR_NORMAL - | PageAttributes::PRESENT -} - -fn ram_block_flags() -> PageAttributes { - // TODO UXN, PXN - PageAttributes::BLOCK - | PageAttributes::ACCESS - | PageAttributes::SH_OUTER - | PageAttributes::PAGE_ATTR_NORMAL - | PageAttributes::PRESENT -} - -// Early mappings -unsafe fn map_early_pages(physical: PhysicalAddress, count: usize) -> Result { - for l3i in 0..512 { - let mut taken = false; - for i in 0..count { - if EARLY_MAPPING_L3[i + l3i].is_present() { - taken = true; - break; - } - } - - if taken { - continue; - } - - for i in 0..count { - let page = physical.add(i * L3::SIZE); - // TODO NX, NC - EARLY_MAPPING_L3[i + l3i] = PageEntry::normal_page(page, PageAttributes::empty()); - tlb_flush_vaae1(EARLY_MAPPING_OFFSET + (l3i + i) * L3::SIZE); - } - - return Ok(EARLY_MAPPING_OFFSET + l3i * L3::SIZE); - } - - Err(Error::OutOfMemory) -} - -unsafe fn unmap_early_page(address: usize) { - if !(EARLY_MAPPING_OFFSET..EARLY_MAPPING_OFFSET + L2::SIZE).contains(&address) { - panic!("Tried to unmap invalid early mapping: {:#x}", address); - } - - let l3i = (address - EARLY_MAPPING_OFFSET).page_index::(); - - assert!(EARLY_MAPPING_L3[l3i].is_present()); - EARLY_MAPPING_L3[l3i] = PageEntry::INVALID; -} - -/// # Safety -/// -/// Only meant to be used by the architecture initialization functions. -pub unsafe fn map_ram_l1(index: usize) { - if index >= RAM_MAPPING_L1_COUNT { - ArchitectureImpl::halt(); - } - let mut tables = KERNEL_TABLES.lock(); - let table_index = index + RAM_MAPPING_START_L1I; - - if tables.l1.data[table_index] != 0 { - ArchitectureImpl::halt(); - } - - tables.l1.data[table_index] = ((index * L1::SIZE) as u64) | ram_block_flags().bits(); - tlb_flush_vaae1(RAM_MAPPING_OFFSET + index * L1::SIZE); -} - -// Device mappings -unsafe fn map_device_memory_l3( - base: PhysicalAddress, - count: usize, - _attrs: DeviceMemoryAttributes, -) -> Result { - // TODO don't map pages if already mapped - - 'l0: for i in 0..DEVICE_MAPPING_L3_COUNT * 512 { - for j in 0..count { - let l2i = (i + j) / 512; - let l3i = (i + j) % 512; - - if DEVICE_MAPPING_L3S[l2i][l3i].is_present() { - continue 'l0; - } - } - - for j in 0..count { - let l2i = (i + j) / 512; - let l3i = (i + j) % 512; - - // TODO NX, NC - DEVICE_MAPPING_L3S[l2i][l3i] = PageEntry::device_page(base.add(j * L3::SIZE)); - tlb_flush_vaae1(DEVICE_MAPPING_OFFSET + l2i * L2::SIZE + l3i * L3::SIZE); - } - - return Ok(DEVICE_MAPPING_OFFSET + i * L3::SIZE); - } - - Err(Error::OutOfMemory) -} - -#[allow(unused)] -unsafe fn map_device_memory_l2( - base: PhysicalAddress, - count: usize, - _attrs: DeviceMemoryAttributes, -) -> Result { - 'l0: for i in DEVICE_MAPPING_L3_COUNT..512 { - for j in 0..count { - if DEVICE_MAPPING_L2[i + j].is_present() { - continue 'l0; - } - } - - for j in 0..count { - DEVICE_MAPPING_L2[i + j] = PageEntry::::device_block(base.add(j * L2::SIZE)); - tlb_flush_vaae1(DEVICE_MAPPING_OFFSET + (i + j) * L2::SIZE); - } - - return Ok(DEVICE_MAPPING_OFFSET + i * L2::SIZE); - } - - Err(Error::OutOfMemory) -} - -pub(crate) unsafe fn map_device_memory( - base: PhysicalAddress, - size: usize, - attrs: DeviceMemoryAttributes, -) -> Result, Error> { - let l3_aligned = base.page_align_down::(); - let l3_offset = base.page_offset::(); - let page_count = (l3_offset + size).page_count::(); - - if page_count > 256 { - // Large mapping, use L2 mapping instead - let l2_aligned = base.page_align_down::(); - let l2_offset = base.page_offset::(); - let page_count = (l2_offset + size).page_count::(); - - let base_address = map_device_memory_l2(l2_aligned, page_count, attrs)?; - let address = base_address + l2_offset; - - Ok(RawDeviceMemoryMapping::from_raw_parts( - l2_aligned.into_u64(), - address, - base_address, - page_count, - L2::SIZE, - )) - } else { - // Just map the pages directly - let base_address = map_device_memory_l3(l3_aligned, page_count, attrs)?; - let address = base_address + l3_offset; - - Ok(RawDeviceMemoryMapping::from_raw_parts( - l3_aligned.into_u64(), - address, - base_address, - page_count, - L3::SIZE, - )) - } -} - -pub(crate) unsafe fn unmap_device_memory(map: &RawDeviceMemoryMapping) { - match map.page_size { - L3::SIZE => { - for i in 0..map.page_count { - let page = map.base_address + i * L3::SIZE; - let l2i = page.page_index::(); - let l3i = page.page_index::(); - assert!(DEVICE_MAPPING_L3S[l2i][l3i].is_present()); - DEVICE_MAPPING_L3S[l2i][l3i] = PageEntry::INVALID; - - tlb_flush_vaae1(page); - } - } - L2::SIZE => todo!(), - _ => unimplemented!(), + let _lock = KERNEL_MEMORY_LOCK.lock(); + fixed::DEVICE_MEMORY.unmap_device_pages(mapping); } } #[inline] -pub fn tlb_flush_asid(asid: u8) { - barrier::dsb(barrier::ISHST); - let value = (asid as u64) << 48; - unsafe { - core::arch::asm!("tlbi aside1, {value}", value = in(reg) value); +pub fn auto_lower_address(ptr: *const T) -> usize { + let address = ptr.addr(); + if address < KERNEL_VIRT_OFFSET { + address + } else { + address - KERNEL_VIRT_OFFSET } - barrier::dsb(barrier::ISH); - barrier::isb(barrier::SY); } #[inline] -pub fn tlb_flush_all() { - barrier::dsb(barrier::ISHST); - unsafe { - core::arch::asm!("tlbi vmalle1is"); - } - barrier::dsb(barrier::ISH); - barrier::isb(barrier::SY); -} - -#[inline] -pub fn tlb_flush_vaae1(page: usize) { - barrier::dsb(barrier::ISHST); - let argument = page >> 12; - unsafe { - core::arch::asm!("tlbi vaae1, {argument}", argument = in(reg) argument); - } - barrier::dsb(barrier::ISH); - barrier::isb(barrier::SY); -} - -pub fn at_s1e0r(input: usize) -> Option { - barrier::dsb(barrier::ISHST); - unsafe { - core::arch::asm!("at s1e0r, {address}", address = in(reg) input); - } - barrier::dsb(barrier::ISH); - barrier::isb(barrier::SY); - if PAR_EL1.matches_all(PAR_EL1::F::TranslationSuccessfull) { - Some(PAR_EL1.read(PAR_EL1::PA)) +pub fn auto_upper_address(ptr: *const T) -> usize { + let address = ptr.addr(); + if address < KERNEL_VIRT_OFFSET { + address + KERNEL_VIRT_OFFSET } else { - None + address } } -pub fn at_s1e1r(input: usize) -> Option { - barrier::dsb(barrier::ISHST); - unsafe { - core::arch::asm!("at s1e1r, {address}", address = in(reg) input); - } - barrier::dsb(barrier::ISH); - barrier::isb(barrier::SY); - if PAR_EL1.matches_all(PAR_EL1::F::TranslationSuccessfull) { - Some(PAR_EL1.read(PAR_EL1::PA)) - } else { - None - } -} - -pub fn ic_iallu() { - atomic::compiler_fence(Ordering::SeqCst); - barrier::dsb(barrier::ISH); - barrier::isb(barrier::SY); - unsafe { - core::arch::asm!("ic iallu"); - } - barrier::isb(barrier::SY); -} - -pub fn dc_cvac(input: usize) { - barrier::dsb(barrier::ISHST); - unsafe { - core::arch::asm!("dc cvac, {address}", address = in(reg) input); - } -} - -fn auto_address(value: *const T) -> usize { - let addr = value.addr(); - if addr < KERNEL_VIRT_OFFSET { - // Called from lower half - addr - } else { - // Called from higher-half - addr - KERNEL_VIRT_OFFSET - } -} - -/// (BSP-early init) loads precomputed kernel mapping tables for the kernel to jump to "higher-half" -/// -/// # Safety -/// -/// Unsafe, must only be called by BSP during its early init while still in "lower-half" -pub unsafe fn load_fixed_tables() { - let ttbr0 = auto_address(&raw const KERNEL_TABLES) as u64; - - TTBR0_EL1.set(ttbr0); - TTBR1_EL1.set(ttbr0); -} - -/// Sets up additional translation tables for kernel usage -/// -/// # Safety -/// -/// Unsafe, must only be called by BSP during its early init, must already be in "higher-half" -pub unsafe fn init_fixed_tables() { - // TODO this could be built in compile-time too? - let mut tables = KERNEL_TABLES.grab(); - let early_mapping_l3_phys = auto_address(&raw const EARLY_MAPPING_L3); - let device_mapping_l2_phys = auto_address(&raw const DEVICE_MAPPING_L2); - - for i in 0..DEVICE_MAPPING_L3_COUNT { - let device_mapping_l3_phys = PhysicalAddress::from_usize( - &DEVICE_MAPPING_L3S[i] as *const _ as usize - KERNEL_VIRT_OFFSET, - ); - DEVICE_MAPPING_L2[i] = PageEntry::table(device_mapping_l3_phys, PageAttributes::empty()); - } - - assert_eq!(tables.l2.data[EARLY_MAPPING_L2I], 0); - tables.l2.data[EARLY_MAPPING_L2I] = - (early_mapping_l3_phys as u64) | kernel_table_flags().bits(); - tlb_flush_vaae1(EARLY_MAPPING_OFFSET); - - assert_eq!(tables.l1.data[DEVICE_MAPPING_L1I], 0); - tables.l1.data[DEVICE_MAPPING_L1I] = - (device_mapping_l2_phys as u64) | kernel_table_flags().bits(); - - tlb_flush_all(); -} - -pub fn setup_memory_attributes() { +fn setup_memory_attributes() { // TODO: Figure out why WriteBack_NonTransient_ReadWriteAlloc doesn't work on Pi 4B MAIR_EL1.write( //// Attribute 0 -- normal memory MAIR_EL1::Attr0_Normal_Inner::WriteBack_NonTransient + - MAIR_EL1::Attr0_Normal_Outer::WriteBack_NonTransient + - //// Attribute 1 -- normal non-cacheable memory - MAIR_EL1::Attr0_Normal_Inner::NonCacheable + - MAIR_EL1::Attr0_Normal_Outer::NonCacheable + - //// Attribute 2 -- device memory - MAIR_EL1::Attr1_Device::nonGathering_nonReordering_EarlyWriteAck, + MAIR_EL1::Attr0_Normal_Outer::WriteBack_NonTransient + + //// Attribute 1 -- normal non-cacheable memory + MAIR_EL1::Attr0_Normal_Inner::NonCacheable + + MAIR_EL1::Attr0_Normal_Outer::NonCacheable + + //// Attribute 2 -- device memory + MAIR_EL1::Attr1_Device::nonGathering_nonReordering_EarlyWriteAck, ); } -/// Enables data cache. -/// -/// # Safety -/// -/// Manipulates low-level machine state, use with care. -pub unsafe fn enable_dcache() { +unsafe fn enable_mmu() { + TCR_EL1.write( + TCR_EL1::AS::ASID8Bits + + TCR_EL1::A1::TTBR0 + + TCR_EL1::HD::CLEAR + + // General + TCR_EL1::IPS::Bits_48 + + // TTBR0 + TCR_EL1::TG0::KiB_4 + TCR_EL1::T0SZ.val(25) + TCR_EL1::SH0::Inner + + // TTBR1 + TCR_EL1::TG1::KiB_4 + TCR_EL1::T1SZ.val(25) + TCR_EL1::SH1::Inner, + ); + barrier::dsb(barrier::ISHST); barrier::isb(barrier::SY); - SCTLR_EL1.modify(SCTLR_EL1::C::Cacheable); + SCTLR_EL1.modify( + SCTLR_EL1::E0E::LittleEndian + + SCTLR_EL1::EE::LittleEndian + + SCTLR_EL1::WXN::Disable + + SCTLR_EL1::SA0::Enable + + SCTLR_EL1::SA::Enable + + SCTLR_EL1::A::Enable + + SCTLR_EL1::I::NonCacheable + + SCTLR_EL1::C::NonCacheable, + ); barrier::dsb(barrier::ISH); barrier::isb(barrier::SY); + + // Enable translation + SCTLR_EL1.modify(SCTLR_EL1::M::Enable); + + // Enable caches + enable_icache(); + enable_dcache(); } -/// Enables instruction cache. -/// -/// # Safety -/// -/// Manipulates low-level machine state, use with care. -pub unsafe fn enable_icache() { - barrier::isb(barrier::SY); - - SCTLR_EL1.modify(SCTLR_EL1::I::Cacheable); - - barrier::dsb(barrier::ISH); - barrier::isb(barrier::SY); -} - -/// Disables instruction cache. -/// -/// # Safety -/// -/// Manipulates low-level machine state, use with care. Might break some instructions. -pub unsafe fn disable_icache() { - barrier::isb(barrier::SY); - - ic_iallu(); - SCTLR_EL1.modify(SCTLR_EL1::I::NonCacheable); - - barrier::dsb(barrier::ISH); - barrier::isb(barrier::SY); +pub unsafe fn init_lower(bsp: bool) { + setup_memory_attributes(); + if bsp { + fixed::setup(); + } + fixed::load(); + enable_mmu(); } diff --git a/kernel/arch/interface/src/lib.rs b/kernel/arch/interface/src/lib.rs index 10d1616c..48f2a57f 100644 --- a/kernel/arch/interface/src/lib.rs +++ b/kernel/arch/interface/src/lib.rs @@ -1,5 +1,11 @@ #![no_std] -#![feature(step_trait, const_trait_impl, never_type, decl_macro)] +#![feature( + step_trait, + const_trait_impl, + never_type, + decl_macro, + generic_const_exprs +)] #![allow(clippy::new_without_default)] use core::ops::Range; @@ -21,8 +27,6 @@ pub mod sync; pub mod task; pub mod util; -#[cfg(any(target_arch = "x86", rust_analyzer))] -pub const KERNEL_VIRT_OFFSET: usize = 0xC0000000; #[cfg(any(target_arch = "aarch64", target_arch = "x86_64", rust_analyzer))] pub const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000; #[cfg(any(target_arch = "riscv64", rust_analyzer))] diff --git a/kernel/arch/interface/src/mem/address.rs b/kernel/arch/interface/src/mem/address.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/kernel/arch/interface/src/mem/mod.rs b/kernel/arch/interface/src/mem/mod.rs index ef2138a1..c31a529e 100644 --- a/kernel/arch/interface/src/mem/mod.rs +++ b/kernel/arch/interface/src/mem/mod.rs @@ -2,9 +2,6 @@ use core::{fmt, marker::PhantomData, mem::size_of, ptr::NonNull}; use yggdrasil_abi::error::Error; -pub mod address; -pub mod table; - pub trait PhysicalMemoryAllocator { type Address; diff --git a/kernel/arch/interface/src/mem/table.rs b/kernel/arch/interface/src/mem/table.rs deleted file mode 100644 index e69de29b..00000000 diff --git a/kernel/arch/riscv64/Cargo.toml b/kernel/arch/riscv64/Cargo.toml index 11c51c16..ffdc6833 100644 --- a/kernel/arch/riscv64/Cargo.toml +++ b/kernel/arch/riscv64/Cargo.toml @@ -16,11 +16,5 @@ static_assertions.workspace = true log.workspace = true cfg-if.workspace = true -[features] -default = [] -riscv64_board_virt = [] -riscv64_board_jh7110 = [] - - [lints] workspace = true diff --git a/kernel/libk/libk-mm/interface/src/device.rs b/kernel/libk/libk-mm/interface/src/device.rs new file mode 100644 index 00000000..a2d7543a --- /dev/null +++ b/kernel/libk/libk-mm/interface/src/device.rs @@ -0,0 +1,132 @@ +use core::ops::Range; + +use kernel_arch_interface::mem::{ + DeviceMemoryAttributes, KernelTableManager, RawDeviceMemoryMapping, +}; +use yggdrasil_abi::error::Error; + +use crate::{ + address::PhysicalAddress, + table::{EntryLevel, EntryLevelExt}, +}; + +pub trait DevicePageTableLevel { + type Level: EntryLevel; + const INDEX_RANGE: Range; + const VIRTUAL_BASE: usize; + + fn map_page(&mut self, index: usize, physical: PhysicalAddress, attrs: &DeviceMemoryAttributes); + fn unmap_page(&mut self, index: usize); + fn is_mapped(&self, index: usize) -> bool; + fn flush_range(range: Range); + + fn allocate_mapping( + &mut self, + base: PhysicalAddress, + page_count: usize, + attrs: &DeviceMemoryAttributes, + ) -> Option { + 'l0: for i in Self::INDEX_RANGE { + for j in 0..page_count { + if self.is_mapped(i + j) { + continue 'l0; + } + } + + for j in 0..page_count { + self.map_page(i + j, base.add(j * Self::Level::SIZE), attrs); + } + + let start = Self::VIRTUAL_BASE + i * Self::Level::SIZE; + Self::flush_range(i..i + page_count); + return Some(start); + } + None + } + + unsafe fn remove_mapping(&mut self, base: usize, page_count: usize) { + let base_index = (base - Self::VIRTUAL_BASE) / Self::Level::SIZE; + for i in 0..page_count { + self.unmap_page(base_index + i); + } + } +} + +pub struct DevicePageManager { + pub normal: N, + pub large: L, +} + +impl DevicePageManager { + pub const fn new(normal: N, large: L) -> Self { + Self { normal, large } + } + + pub unsafe fn map_device_pages( + &mut self, + base: PhysicalAddress, + size: usize, + attrs: DeviceMemoryAttributes, + ) -> Result, Error> { + let small_aligned_base = base.page_align_down::(); + let small_aligned_end = base.add(size).page_align_up::(); + let small_offset = base - small_aligned_base; + let small_page_count = (small_aligned_end - small_aligned_base).page_count::(); + + if small_page_count > 128 { + // Allocate from large page pool + let large_aligned_base = base.page_align_down::(); + let large_aligned_end = base.add(size).page_align_up::(); + let large_offset = base - large_aligned_base; + let large_page_count = + (large_aligned_end - large_aligned_base).page_count::(); + + let mapped_base = self + .large + .allocate_mapping(large_aligned_base, large_page_count, &attrs) + .ok_or(Error::OutOfMemory)?; + let mapped_address = mapped_base + large_offset; + + Ok(RawDeviceMemoryMapping::from_raw_parts( + large_aligned_base.into_u64(), + mapped_address, + mapped_base, + large_page_count, + L::Level::SIZE, + )) + } else { + // Allocate from small page pool + let mapped_base = self + .normal + .allocate_mapping(small_aligned_base, small_page_count, &attrs) + .ok_or(Error::OutOfMemory)?; + let mapped_address = mapped_base + small_offset; + + Ok(RawDeviceMemoryMapping::from_raw_parts( + small_aligned_base.into_u64(), + mapped_address, + mapped_base, + small_page_count, + N::Level::SIZE, + )) + } + } + + pub unsafe fn unmap_device_pages( + &mut self, + mapping: &RawDeviceMemoryMapping, + ) { + if mapping.page_size == N::Level::SIZE { + self.normal + .remove_mapping(mapping.base_address, mapping.page_count); + } else if mapping.page_size == L::Level::SIZE { + self.large + .remove_mapping(mapping.base_address, mapping.page_count); + } else { + unreachable!( + "Invalid device memory mapping with page size {:#x}", + mapping.page_size + ) + } + } +} diff --git a/kernel/libk/libk-mm/interface/src/lib.rs b/kernel/libk/libk-mm/interface/src/lib.rs index 04cfb419..06ce3d10 100644 --- a/kernel/libk/libk-mm/interface/src/lib.rs +++ b/kernel/libk/libk-mm/interface/src/lib.rs @@ -7,6 +7,7 @@ use address::{AsPhysicalAddress, PhysicalAddress}; use kernel_arch_interface::KERNEL_VIRT_OFFSET; pub mod address; +pub mod device; pub mod pointer; pub mod process; pub mod table; diff --git a/kernel/libk/libk-mm/src/phys/mod.rs b/kernel/libk/libk-mm/src/phys/mod.rs index dca93441..cfaf7c29 100644 --- a/kernel/libk/libk-mm/src/phys/mod.rs +++ b/kernel/libk/libk-mm/src/phys/mod.rs @@ -178,20 +178,14 @@ pub fn find_contiguous_region>( /// /// The caller must ensure this function has not been called before and that the regions /// are valid and actually available. -pub unsafe fn init_from_iter< - I: Iterator + Clone, - Map: FnOnce(I, PhysicalAddress, PhysicalAddress) -> Result<(), Error>, ->( +pub unsafe fn init_from_iter + Clone>( it: I, - map_physical_memory: Map, ) -> Result<(), Error> { // Map the physical memory let (phys_start, phys_end) = physical_memory_range(it.clone()).unwrap(); reserve_region("kernel", kernel_physical_memory_region()); - map_physical_memory(it.clone(), phys_start, phys_end)?; - let total_count = (phys_end - phys_start) / L3_PAGE_SIZE; let page_bitmap_size = (total_count + BITMAP_WORD_SIZE - 1) / (BITMAP_WORD_SIZE / 8); let page_bitmap_page_count = page_bitmap_size.div_ceil(L3_PAGE_SIZE); diff --git a/kernel/src/arch/aarch64/boot/entry.S b/kernel/src/arch/aarch64/boot/entry.S index e94d3a6c..452232f0 100644 --- a/kernel/src/arch/aarch64/boot/entry.S +++ b/kernel/src/arch/aarch64/boot/entry.S @@ -1,62 +1,18 @@ -.set CNTHCTL_EL2_EL1PCTEN, 1 << 0 -.set CNTHCTL_EL2_EL1PCEN, 1 << 1 - -.set HCR_EL2_RW_EL1IsAArch64, 1 << 31 - -.set SCTLR_EL2_RES1, 0x30C50830 - -.set SPSR_EL2_EL1h, 0x5 -.set SPSR_EL2_MASK_DAIF, 0xF << 6 - -.macro MOV_L reg, value - mov \reg, #((\value) & 0xFFFF) - movk \reg, #((\value) >> 16), lsl #16 -.endm - -.macro MOV_ABS reg, sym - movz \reg, #:abs_g2:\sym - movk \reg, #:abs_g1_nc:\sym - movk \reg, #:abs_g0_nc:\sym -.endm - -// clobbers: x1 -.macro LEAVE_EL2 destination - // Setup EL1 physical timer - mrs x1, cnthctl_el2 - orr x1, x1, #(1 << 0) // EL0PCTEN = 1 - orr x1, x1, #(1 << 1) // EL0VCTEN = 1 - orr x1, x1, #(1 << 10) // EL1PCTEN = 1 - orr x1, x1, #(1 << 11) // EL1PTEN = 1 - msr cnthctl_el2, x1 - mov x1, #1 - msr cnthp_ctl_el2, x1 - msr cntkctl_el1, xzr - msr cntvoff_el2, xzr - - mov x1, #(1 << 31) // RW = 1, EL1 is AArch64 - orr x1, x1, #(1 << 1) // SWIO = 1 (Pi has this hardwired) - msr hcr_el2, x1 - - // Return to EL1 - mov x1, #0x3C5 - msr spsr_el2, x1 - adr x1, \destination - msr elr_el2, x1 - eret -.endm - .global __aarch64_entry .global __aarch64_ap_entry .global __aarch64_ap_spin_table_entry -.extern __kernel_end -.extern __kernel_start +.macro ADR_WIDE reg, sym + adrp \reg, \sym + add \reg, \reg, :lo12:\sym +.endm -.section .text.entry +.pushsection .text.entry __aarch64_entry: + // Image header ccmp x18, #0, #0xd, pl // "MZ" magic b __aarch64_real_entry // Jump to real entry - .quad 0x200000 // Image load offset from start of RAM + .quad 0x80000 // Image load offset from start of RAM .quad __kernel_size // Kernel size .quad 0 // Kernel flags .quad 0 // reserved @@ -64,136 +20,78 @@ __aarch64_entry: .quad 0 // reserved .ascii "ARM\x64" .long 0 + +// x0 -- dtb physical address __aarch64_real_entry: - // x0 -- dtb_phys + adr x29, __aarch64_entry + mov x30, x0 - ////////////////////////////// - // Check CPU index // - ////////////////////////////// - mrs x1, mpidr_el1 - ands x1, x1, #3 - bne .spin_wait + //// Halt non-BSP cores + mrs x0, mpidr_el1 + ands x0, x0, #0xF + bne .ap_spin_loop - ////////////////////////////// - // Check CurrentEL // - ////////////////////////////// - mrs x1, CurrentEL - adr x2, .bsp_el_table - add x2, x2, x1 - br x2 - -// TODO code for leaving EL3 -.bsp_el3: - b . - -.bsp_el2: - ////////////////////////////// - // Leave EL2 // - ////////////////////////////// - - LEAVE_EL2 .bsp_el1 - -.bsp_el1: - ////////////////////////////// - // Setup EL1 for Rust entry // - ////////////////////////////// - - // Load proper SP - MOV_ABS x1, {stack_bottom} + {stack_size} - {kernel_virt_offset} - mov sp, x1 - - // Zero .bss - MOV_ABS x1, __bss_start_phys - MOV_ABS x2, __bss_size - lsr x2, x2, #3 - cbz x2, 11f -10: - str xzr, [x1] - add x1, x1, #8 - subs x2, x2, #1 - bne 10b -11: - - // Perform Rust code entry - bl {bsp_el1_entry} - {kernel_virt_offset} - b . - -// EL0 impossible -.bsp_el0: - udf #0 - -.spin_wait: - // AP in a SMP system - // TODO spin loop for this method of init - wfe - b .spin_wait - -.p2align 3 -.bsp_el_table: - b .bsp_el0 - b .bsp_el1 - b .bsp_el2 - b .bsp_el3 - -////////////////////////////// -// AP startup code // -////////////////////////////// - -.section .text -__aarch64_ap_spin_table_entry: - // Spin-table entry, expected state: - // * MMU is not yet enabled - // * In lower half - // * x0 is uninitialized - MOV_ABS x1, {spin_table_stack} - {kernel_virt_offset} - - // Atomic load-acquire the stack address - ldar x0, [x1] - - dsb ish - isb sy - - // Fall through to __aarch64_ap_entry - -__aarch64_ap_entry: - // Application processsor entry, expected state: - // * MMU is not yet enabled - // * In lower half - // * x0 -- physical stack pointer - - mrs x1, CurrentEL - lsr x1, x1, #2 - and x1, x1, #3 - adr x2, .el_table_ap - ldr x2, [x2, x1, lsl #3] - br x2 - - b . - -// TODO code to leave EL3 on AP -.ap_el3: - b . - -.ap_el2: - LEAVE_EL2 .ap_el1 - -.ap_el1: - dsb ish - isb sy + //// Zero .bss + adrp x0, __bss_start + adrp x1, __bss_end +1: + cmp x0, x1 + beq 2f + stp xzr, xzr, [x0], #16 + b 1b +2: + //// Setup a stack + ADR_WIDE x0, {bsp_stack_bottom} + {bsp_stack_size} mov sp, x0 - MOV_ABS x0, {ap_el1_entry} - {kernel_virt_offset} - blr x0 + //// Store boot parameters + ADR_WIDE x0, {kernel_load_base} + str x29, [x0] + ADR_WIDE x0, {dtb_physical_address} + str x30, [x0] + + //// Relocate the kernel + mov x0, x29 + ADR_WIDE x1, __rela_start + ADR_WIDE x2, __rela_end + bl {relocate_kernel} + + //// Branch to appropriate ELn code + mrs x0, currentel + adr x1, .bsp_el_branch_table + add x0, x0, x1 + br x0 + +.bsp_el_branch_table: + b . // EL0 impossible + b {bsp_entry_el1} + b {bsp_entry_el2} + b . // TODO: EL3 + +.ap_spin_loop: + wfe + b .ap_spin_loop + +.popsection // .text.entry + +.pushsection .text +__aarch64_ap_entry: + // x0 - physical stack pointer + mov sp, x0 + + mrs x2, currentel + adr x1, .ap_el_branch_table + add x1, x1, x2 + br x1 + +// TODO +__aarch64_ap_spin_table_entry: b . -// EL0 impossible -.ap_el0: - udf #0 - -.p2align 3 -.el_table_ap: - .dword .ap_el0 - {kernel_virt_offset} - .dword .ap_el1 - {kernel_virt_offset} - .dword .ap_el2 - {kernel_virt_offset} - .dword .ap_el3 - {kernel_virt_offset} +.ap_el_branch_table: + b . + b {ap_entry_el1} + b {ap_entry_el2} + b . +.popsection // .text diff --git a/kernel/src/arch/aarch64/boot/mod.rs b/kernel/src/arch/aarch64/boot/mod.rs index eaa37be5..93293988 100644 --- a/kernel/src/arch/aarch64/boot/mod.rs +++ b/kernel/src/arch/aarch64/boot/mod.rs @@ -1,14 +1,19 @@ //! AArch64 boot and entry implementation + use core::{ arch::global_asm, - sync::atomic::{AtomicUsize, Ordering}, + sync::atomic::{self, AtomicUsize, Ordering}, }; use aarch64_cpu::{ asm::barrier, - registers::{CPACR_EL1, ID_AA64MMFR0_EL1, SCTLR_EL1, TCR_EL1, TTBR0_EL1}, + registers::{ + CNTHCTL_EL2, CNTHP_CTL_EL2, CNTKCTL_EL1, CNTVOFF_EL2, CPACR_EL1, ELR_EL2, HCR_EL2, + SPSR_EL2, SP_EL1, TTBR0_EL1, + }, }; -use kernel_arch::{absolute_address, Architecture, ArchitectureImpl}; +use elf::{abi, relocation::Elf64_Rela}; +use kernel_arch::{Architecture, ArchitectureImpl, KERNEL_VIRT_OFFSET}; use kernel_arch_aarch64::{ mem::{self, table::L3}, CPU_COUNT, @@ -22,104 +27,94 @@ use libk_mm::{ phys, table::EntryLevel, }; -use tock_registers::interfaces::{ReadWriteable, Readable, Writeable}; +use tock_registers::interfaces::{ReadWriteable, Writeable}; -use super::{exception, BootStack, PLATFORM}; use crate::{ - arch::aarch64::BOOT_STACK_SIZE, kernel_main, kernel_secondary_main, mem::KERNEL_VIRT_OFFSET, + arch::{ + aarch64::{exception, BootStack, BOOT_STACK_SIZE}, + PLATFORM, + }, + kernel_main, kernel_secondary_main, }; -unsafe fn check_mmu_features() { - if ID_AA64MMFR0_EL1.matches_all(ID_AA64MMFR0_EL1::TGran4::NotSupported) { - // TODO early panic +static BSP_STACK: BootStack = BootStack::zeroed(); +pub(crate) static SPIN_TABLE_STACK: AtomicUsize = AtomicUsize::new(0); +static mut KERNEL_LOAD_BASE: u64 = 0; +static mut DTB_PHYSICAL_ADDRESS: PhysicalAddress = PhysicalAddress::ZERO; + +unsafe extern "C" fn relocate_kernel(image_base: i64, rela_start: usize, rela_end: usize) { + let rela_count = (rela_end - rela_start) / size_of::(); + let rela_ptr: *const Elf64_Rela = core::ptr::with_exposed_provenance(rela_start); + let rela_table = core::slice::from_raw_parts(rela_ptr, rela_count); + + for rela in rela_table { + let slot: *mut i64 = + core::ptr::with_exposed_provenance_mut(rela.r_offset as usize + image_base as usize); + + let value = match rela.r_info as u32 { + abi::R_AARCH64_RELATIVE => rela.r_addend + image_base, + _ => loop {}, + }; + + slot.write_volatile(value); + } +} + +fn setup_cpu_common() { + CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNothing); +} + +unsafe fn leave_el2(pc: usize, sp: usize, x0: usize) -> ! { + CNTHCTL_EL2.write(CNTHCTL_EL2::EL1PCEN::SET + CNTHCTL_EL2::EL1PCTEN::SET); + CNTHP_CTL_EL2.write(CNTHP_CTL_EL2::ENABLE::SET); + CNTKCTL_EL1.set(0); + CNTVOFF_EL2.set(0); + + HCR_EL2.write(HCR_EL2::RW::EL1IsAarch64 + HCR_EL2::SWIO::SET); + + SPSR_EL2.write( + SPSR_EL2::D::SET + + SPSR_EL2::A::SET + + SPSR_EL2::I::SET + + SPSR_EL2::F::SET + + SPSR_EL2::M::EL1h, + ); + + ELR_EL2.set(pc as u64); + SP_EL1.set(sp as u64); + core::arch::asm!("eret", in("x0") x0, options(noreturn)); +} + +#[inline] +unsafe fn long_jump(pc: usize, sp: usize) -> ! { + core::arch::asm!("mov sp, {sp}; br {pc}", sp = in(reg) sp, pc = in(reg) pc, options(noreturn)); +} + +unsafe extern "C" fn bsp_entry_upper() -> ! { + // Relocate the kernel again + extern "C" { + static __rela_start: u8; + static __rela_end: u8; + } + + atomic::fence(Ordering::SeqCst); + let rela_start = (&raw const __rela_start).addr(); + let rela_end = (&raw const __rela_end).addr(); + let image_base = (KERNEL_VIRT_OFFSET as u64 + KERNEL_LOAD_BASE) as i64; + relocate_kernel(image_base, rela_start, rela_end); + atomic::fence(Ordering::SeqCst); + + // Setup memory management (using DTB from lower half) + if let Err(error) = PLATFORM.init_memory_management(DTB_PHYSICAL_ADDRESS) { + let _ = error; ArchitectureImpl::halt(); } -} -unsafe fn pre_init_mmu() { - mem::setup_memory_attributes(); - - TCR_EL1.write( - TCR_EL1::AS::ASID8Bits + - TCR_EL1::A1::TTBR0 + - TCR_EL1::HD::CLEAR + - // General - TCR_EL1::IPS::Bits_48 + - // TTBR0 - TCR_EL1::TG0::KiB_4 + TCR_EL1::T0SZ.val(25) + TCR_EL1::SH0::Inner + - // TTBR1 - TCR_EL1::TG1::KiB_4 + TCR_EL1::T1SZ.val(25) + TCR_EL1::SH1::Inner, - ); -} - -unsafe fn enable_mmu() { - barrier::dsb(barrier::ISHST); - barrier::isb(barrier::SY); - - SCTLR_EL1.modify( - SCTLR_EL1::E0E::LittleEndian - + SCTLR_EL1::EE::LittleEndian - + SCTLR_EL1::WXN::Disable - + SCTLR_EL1::SA0::Enable - + SCTLR_EL1::SA::Enable - + SCTLR_EL1::A::Enable - + SCTLR_EL1::I::NonCacheable - + SCTLR_EL1::C::NonCacheable, - ); - - barrier::dsb(barrier::ISH); - barrier::isb(barrier::SY); - - // Enable translation - SCTLR_EL1.modify(SCTLR_EL1::M::Enable); - - // Enable caches - mem::enable_icache(); - mem::enable_dcache(); -} - -unsafe fn enter_higher_half(sp: usize, elr: usize, x0: usize) -> ! { - unsafe { - core::arch::asm!(r#" - mov sp, {sp} - mov x0, {x0} - mov lr, xzr - br {elr} - "#, elr = in(reg) elr, sp = in(reg) sp, x0 = in(reg) x0, options(noreturn)); - } -} - -// NOTE executes in "lower-half" address space, MMU not yet enabled -unsafe extern "C" fn __aarch64_el1_bsp_lower_entry(dtb: PhysicalAddress) -> ! { - ArchitectureImpl::set_interrupt_mask(true); - - // Don't trap FP operations - CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNothing); - - // Setup MMU to jump to "higher-half" address space - check_mmu_features(); - pre_init_mmu(); - kernel_arch_aarch64::mem::load_fixed_tables(); - enable_mmu(); - - // SP points to the .bss section, so it's +offset mapped - let sp = BSP_STACK.top_addr() + KERNEL_VIRT_OFFSET; - let elr = absolute_address!(__aarch64_bsp_upper_entry); - - enter_higher_half(sp, elr, dtb.into_usize()); -} - -unsafe extern "C" fn __aarch64_bsp_upper_entry(dtb: PhysicalAddress) -> ! { // Remove the "lower-half" mapping, no longer needed TTBR0_EL1.set(0); mem::tlb_flush_all(); - // Setup the "runtime" part of the kernel tables - if PLATFORM.init_memory_management(dtb).is_err() { - ArchitectureImpl::halt(); - } - barrier::dsb(barrier::ISHST); barrier::isb(barrier::SY); @@ -138,32 +133,7 @@ unsafe extern "C" fn __aarch64_bsp_upper_entry(dtb: PhysicalAddress) -> ! { kernel_main() } -// TODO re-implement for Pi 4B -unsafe extern "C" fn __aarch64_el1_ap_lower_entry() -> ! { - const AP_STACK_PAGES: usize = 8; - ArchitectureImpl::set_interrupt_mask(true); - - // Unmask FP operations - CPACR_EL1.modify(CPACR_EL1::FPEN::TrapNothing); - - check_mmu_features(); - pre_init_mmu(); - kernel_arch_aarch64::mem::load_fixed_tables(); - enable_mmu(); - - let stack_pages = phys::alloc_pages_contiguous(AP_STACK_PAGES).unwrap(); - let stack_base = stack_pages.virtualize(); - let sp = stack_base + L3::SIZE * AP_STACK_PAGES; - - let elr = absolute_address!(__aarch64_ap_upper_entry); - - barrier::dsb(barrier::ISH); - barrier::isb(barrier::SY); - - enter_higher_half(sp, elr, 0); -} - -extern "C" fn __aarch64_ap_upper_entry() -> ! { +unsafe extern "C" fn ap_entry_upper() -> ! { // Flush lower half TTBR0_EL1.set(0); @@ -188,16 +158,50 @@ extern "C" fn __aarch64_ap_upper_entry() -> ! { kernel_secondary_main() } -#[link_section = ".bss"] -static BSP_STACK: BootStack = BootStack::zeroed(); -pub(crate) static SPIN_TABLE_STACK: AtomicUsize = AtomicUsize::new(0); +unsafe extern "C" fn bsp_entry_el1() -> ! { + setup_cpu_common(); + mem::init_lower(true); + let pc = (bsp_entry_upper as usize) + KERNEL_VIRT_OFFSET; + let sp = BSP_STACK.top_addr() + KERNEL_VIRT_OFFSET; + long_jump(pc, sp) +} + +unsafe extern "C" fn bsp_entry_el2() -> ! { + leave_el2(bsp_entry_el1 as usize, BSP_STACK.top_addr(), 0) +} + +unsafe extern "C" fn ap_entry_el1(sp: usize) -> ! { + let _ = sp; + const AP_STACK_PAGES: usize = 8; + + setup_cpu_common(); + mem::init_lower(false); + + let stack_pages = phys::alloc_pages_contiguous(AP_STACK_PAGES).unwrap(); + let stack_base = stack_pages.virtualize(); + let sp = stack_base + L3::SIZE * AP_STACK_PAGES; + + let pc = (ap_entry_upper as usize) + KERNEL_VIRT_OFFSET; + long_jump(pc, sp) +} + +unsafe extern "C" fn ap_entry_el2(sp: usize) -> ! { + leave_el2(ap_entry_el1 as usize, sp, sp) +} global_asm!( include_str!("entry.S"), - bsp_el1_entry = sym __aarch64_el1_bsp_lower_entry, - ap_el1_entry = sym __aarch64_el1_ap_lower_entry, - spin_table_stack = sym SPIN_TABLE_STACK, - stack_bottom = sym BSP_STACK, - kernel_virt_offset = const KERNEL_VIRT_OFFSET, - stack_size = const BOOT_STACK_SIZE + + kernel_load_base = sym KERNEL_LOAD_BASE, + dtb_physical_address = sym DTB_PHYSICAL_ADDRESS, + + bsp_stack_size = const BOOT_STACK_SIZE, + bsp_stack_bottom = sym BSP_STACK, + bsp_entry_el1 = sym bsp_entry_el1, + bsp_entry_el2 = sym bsp_entry_el2, + + ap_entry_el1 = sym ap_entry_el1, + ap_entry_el2 = sym ap_entry_el2, + + relocate_kernel = sym relocate_kernel, ); diff --git a/kernel/src/arch/aarch64/mod.rs b/kernel/src/arch/aarch64/mod.rs index 0f2766c0..cc15d760 100644 --- a/kernel/src/arch/aarch64/mod.rs +++ b/kernel/src/arch/aarch64/mod.rs @@ -3,7 +3,6 @@ use core::sync::atomic::{self, Ordering}; use aarch64_cpu::registers::{CNTP_CTL_EL0, CNTP_TVAL_EL0}; -use abi::error::Error; use alloc::sync::Arc; use device_api::{ interrupt::{Irq, LocalInterruptController}, @@ -13,15 +12,8 @@ use device_tree::{ driver::{unflatten_device_tree, InitSequence}, DeviceTree, DeviceTreeNodeExt, }; -use kernel_arch_aarch64::{ - mem::{ - self, - table::{L1, L3}, - EarlyMapping, MEMORY_LIMIT, RAM_MAPPING_L1_COUNT, - }, - ArchitectureImpl, PerCpuData, -}; -use libk::{arch::Cpu, config, debug, device::external_interrupt_controller}; +use kernel_arch_aarch64::{mem, ArchitectureImpl, PerCpuData}; +use libk::{arch::Cpu, config, debug, device::external_interrupt_controller, error::Error}; use libk_mm::{ address::PhysicalAddress, phys::{self, reserved::reserve_region, PhysicalMemoryRegion}, @@ -33,16 +25,12 @@ use tock_registers::interfaces::Writeable; use ygg_driver_pci::PciBusManager; use crate::{ - // device::power::arm_psci::Psci, + arch::{aarch64::gic::Gic, Platform}, device::{power::arm_psci::Psci, MACHINE_NAME}, fs::{Initrd, INITRD_DATA}, util::call_init_array, }; -use self::gic::Gic; - -use super::Platform; - pub mod boot; pub mod exception; pub mod gic; @@ -51,6 +39,9 @@ pub mod timer; const BOOT_STACK_SIZE: usize = 4096 * 32; +/// Alias for terminal-level page tables +pub type L3 = mem::table::L3; + #[derive(Clone, Copy)] #[repr(C, align(0x20))] struct BootStack { @@ -60,7 +51,6 @@ struct BootStack { /// AArch64 architecture implementation pub struct AArch64 { dt: OneTimeInit>, - /// Optional instance of PSCI on this platform pub psci: OneTimeInit>, reset: OneTimeInit>, @@ -79,10 +69,6 @@ impl BootStack { } impl Platform for AArch64 { - const KERNEL_VIRT_OFFSET: usize = 0xFFFFFF8000000000; - - type L3 = L3; - unsafe fn start_application_processors(&self) { if let Some(compatible) = self.machine_compatible.try_get() { if *compatible == "raspberrypi,4-model-b" { @@ -96,12 +82,12 @@ impl Platform for AArch64 { log::error!("Could not initialize AP CPUs: {:?}", error); } } - - fn register_reset_device(&self, reset: Arc) -> Result<(), Error> { - self.reset.init(reset); - Ok(()) - } - + // + // fn register_reset_device(&self, reset: Arc) -> Result<(), Error> { + // self.reset.init(reset); + // Ok(()) + // } + // unsafe fn reset(&self) -> ! { if let Some(reset) = self.reset.try_get() { reset.reset() @@ -112,55 +98,30 @@ impl Platform for AArch64 { } } -static GIC: OneTimeInit> = OneTimeInit::new(); - impl AArch64 { fn set_gic(gic: Arc) { GIC.init(gic); } - fn map_physical_memory + Clone>( - _it: I, - _memory_start: PhysicalAddress, - memory_end: PhysicalAddress, + #[inline(never)] + unsafe fn init_memory_management( + &'static self, + dtb_address: PhysicalAddress, ) -> Result<(), Error> { - let end_l1i = memory_end.page_align_up::().page_index::(); - if end_l1i > RAM_MAPPING_L1_COUNT { - panic!("TODO: partial physical memory mapping"); - } - - // Map 1GiB chunks - for index in 0..end_l1i { - unsafe { - kernel_arch_aarch64::mem::map_ram_l1(index); - } - } - - MEMORY_LIMIT.store(memory_end.into_usize(), Ordering::Release); - - Ok(()) - } - - unsafe fn init_memory_management(&'static self, dtb: PhysicalAddress) -> Result<(), Error> { - // Initialize the runtime mappings - kernel_arch_aarch64::mem::init_fixed_tables(); - - // Extract the size of the device tree - let dtb_size = { - let dtb_header = EarlyMapping::::map_slice(dtb, DeviceTree::MIN_HEADER_SIZE)?; - DeviceTree::read_totalsize(dtb_header.as_ref()).map_err(|_| Error::InvalidArgument)? - }; + let dtb: PhysicalRef<[u8]> = + PhysicalRef::map_slice(dtb_address, DeviceTree::MIN_HEADER_SIZE); + let dtb_size = DeviceTree::read_totalsize(&dtb[..]).map_err(|_| Error::InvalidArgument)?; reserve_region( "dtb", PhysicalMemoryRegion { - base: dtb, + base: dtb_address, size: (dtb_size + 0xFFF) & !0xFFF, }, ); - let dtb_slice = EarlyMapping::::map_slice(dtb, dtb_size)?; - let dt = DeviceTree::from_raw(dtb_slice.as_ptr() as usize)?; + let dtb: PhysicalRef<[u8]> = PhysicalRef::map_slice(dtb_address, dtb_size); + let dt = DeviceTree::from_raw(dtb.as_ptr().addr())?; // Setup initrd from the dt let initrd = dt.chosen_initrd(); @@ -179,15 +140,10 @@ impl AArch64 { ); } + let dt = self.dt.init(dt); + // Initialize the physical memory - phys::init_from_iter(dt.memory_regions(), Self::map_physical_memory)?; - - // EarlyMapping for DTB no longer needed, it lives in physical memory and can be obtained - // through PhysicalRef - let dtb_slice: PhysicalRef<'static, [u8]> = PhysicalRef::map_slice(dtb, dtb_size); - let dt = DeviceTree::from_raw(dtb_slice.as_ptr().addr())?; - - self.dt.init(dt); + phys::init_from_iter(dt.memory_regions())?; // Setup initrd if let Some((initrd_start, initrd_end)) = initrd { @@ -333,8 +289,8 @@ impl AArch64 { pub static PLATFORM: AArch64 = AArch64 { dt: OneTimeInit::new(), initrd: OneTimeInit::new(), - psci: OneTimeInit::new(), reset: OneTimeInit::new(), machine_compatible: OneTimeInit::new(), }; +static GIC: OneTimeInit> = OneTimeInit::new(); diff --git a/kernel/src/arch/aarch64/smp.rs b/kernel/src/arch/aarch64/smp.rs index 2490f307..8f2eb7b0 100644 --- a/kernel/src/arch/aarch64/smp.rs +++ b/kernel/src/arch/aarch64/smp.rs @@ -128,7 +128,7 @@ pub unsafe fn start_ap_cores(dt: &DeviceTree) -> Result<(), Error> { let sp = AP_TRAMPOLINE_STACK.top_addr() - KERNEL_VIRT_OFFSET; for cpu in enumerate_cpus(dt).filter(|cpu| cpu.id != 0) { - log::debug!( + log::info!( "cpu{}: enable-method={:x?}, compatible={:?}, sp={:#x}", cpu.id, cpu.enable_method, diff --git a/kernel/src/arch/mod.rs b/kernel/src/arch/mod.rs index 6a684429..6260dd1b 100644 --- a/kernel/src/arch/mod.rs +++ b/kernel/src/arch/mod.rs @@ -1,55 +1,37 @@ //! Provides architecture/platform-specific implementation details -use abi::error::Error; - -use alloc::sync::Arc; -use device_api::{ - interrupt::{IpiDeliveryTarget, IpiMessage}, - ResetDevice, -}; use kernel_arch::{Architecture, ArchitectureImpl}; -use libk_mm::table::EntryLevel; #[cfg(any(target_arch = "aarch64", rust_analyzer))] pub mod aarch64; #[cfg(any(target_arch = "aarch64", rust_analyzer))] -pub use aarch64::{AArch64 as PlatformImpl, PLATFORM}; - -#[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))] -pub mod x86; - -#[cfg(any(target_arch = "x86_64", rust_analyzer))] -pub mod x86_64; -#[cfg(any(target_arch = "x86_64", rust_analyzer))] -pub use x86_64::{PLATFORM, X86_64 as PlatformImpl}; - -#[cfg(any(target_arch = "riscv64", rust_analyzer))] -pub mod riscv64; -#[cfg(any(target_arch = "riscv64", rust_analyzer))] -pub use riscv64::{Riscv64 as PlatformImpl, PLATFORM}; - -#[cfg(not(any( - target_arch = "x86_64", - target_arch = "aarch64", - target_arch = "riscv64", - target_arch = "x86" -)))] -compile_error!("Unsupported architecture"); - -/// Architecture-specific lowest level of page mapping -pub type L3 = ::L3; +pub use aarch64::{AArch64 as PlatformImpl, L3, PLATFORM}; +// +// #[cfg(any(target_arch = "x86_64", target_arch = "x86", rust_analyzer))] +// pub mod x86; +// +// #[cfg(any(target_arch = "x86_64", rust_analyzer))] +// pub mod x86_64; +// #[cfg(any(target_arch = "x86_64", rust_analyzer))] +// pub use x86_64::{PLATFORM, X86_64 as PlatformImpl}; +// +// #[cfg(any(target_arch = "riscv64", rust_analyzer))] +// pub mod riscv64; +// #[cfg(any(target_arch = "riscv64", rust_analyzer))] +// pub use riscv64::{Riscv64 as PlatformImpl, PLATFORM}; +// +// #[cfg(not(any( +// target_arch = "x86_64", +// target_arch = "aarch64", +// target_arch = "riscv64", +// target_arch = "x86" +// )))] +// compile_error!("Unsupported architecture"); // Architecture interfaces /// Interface for an architecture-specific facilities -#[allow(unused)] pub trait Platform { - /// Address, to which "zero" address is mapped in the virtual address space - const KERNEL_VIRT_OFFSET: usize; - - /// Lowest page entry level, usually 4KiB pages - type L3: EntryLevel; - /// Starts up the application processors that may be present in the system. /// /// # Safety @@ -57,32 +39,6 @@ pub trait Platform { /// Only safe to call once during system init. unsafe fn start_application_processors(&self) {} - // Architecture intrinsics - - /// Adds a reset device to the system - fn register_reset_device(&self, reset: Arc) -> Result<(), Error> { - Err(Error::NotImplemented) - } - - /// Sends a message to the requested set of CPUs through an interprocessor interrupt. - /// - /// # Note - /// - /// u64 limits the number of targetable CPUs to (only) 64. Platform-specific implementations - /// may impose narrower restrictions. - /// - /// # Safety - /// - /// As the call may alter the flow of execution on CPUs, this function is unsafe. - unsafe fn send_ipi(&self, target: IpiDeliveryTarget, msg: IpiMessage) -> Result { - if let Some(intc) = ArchitectureImpl::local_interrupt_controller() { - intc.send_ipi(target, msg).map(|_| true) - } else { - log::debug!("No local interrupt controller -> no IPI"); - Ok(false) - } - } - /// Performs a CPU reset. /// /// # Safety @@ -95,4 +51,28 @@ pub trait Platform { ArchitectureImpl::wait_for_interrupt(); } } + + // /// Adds a reset device to the system + // fn register_reset_device(&self, reset: Arc) -> Result<(), Error> { + // Err(Error::NotImplemented) + // } + // + // /// Sends a message to the requested set of CPUs through an interprocessor interrupt. + // /// + // /// # Note + // /// + // /// u64 limits the number of targetable CPUs to (only) 64. Platform-specific implementations + // /// may impose narrower restrictions. + // /// + // /// # Safety + // /// + // /// As the call may alter the flow of execution on CPUs, this function is unsafe. + // unsafe fn send_ipi(&self, target: IpiDeliveryTarget, msg: IpiMessage) -> Result { + // if let Some(intc) = ArchitectureImpl::local_interrupt_controller() { + // intc.send_ipi(target, msg).map(|_| true) + // } else { + // log::debug!("No local interrupt controller -> no IPI"); + // Ok(false) + // } + // } } diff --git a/kernel/src/init.rs b/kernel/src/init.rs index 7f02ec50..f49223d9 100644 --- a/kernel/src/init.rs +++ b/kernel/src/init.rs @@ -78,6 +78,7 @@ pub fn kinit() -> Result<(), Error> { .ok(); ygg_driver_net_loopback::init(); + ygg_driver_net_core::start_network_tasks()?; random::init(); diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 8f3962aa..a2b25874 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -37,7 +37,6 @@ use abi::{error::Error, io::FileMode}; use alloc::string::String; -use arch::Platform; use git_version::git_version; use kernel_arch::{Architecture, ArchitectureImpl}; use libk::{ @@ -53,11 +52,15 @@ use libk::{ }; use libk_util::sync::SpinFence; -use crate::{arch::PLATFORM, task::spawn_kernel_closure}; +use crate::{ + arch::{Platform, PLATFORM}, + task::spawn_kernel_closure, +}; extern crate yggdrasil_abi as abi; extern crate alloc; + #[cfg(not(rust_analyzer))] extern crate compiler_builtins; @@ -75,12 +78,10 @@ cfg_if::cfg_if! { } } -#[macro_use] -pub mod arch; - #[cfg(any(target_arch = "riscv64", rust_analyzer))] extern crate ygg_driver_net_stmmac; +pub mod arch; pub mod device; pub mod fs; pub mod init; diff --git a/kernel/src/mem/mod.rs b/kernel/src/mem/mod.rs index 294141e0..97cddbac 100644 --- a/kernel/src/mem/mod.rs +++ b/kernel/src/mem/mod.rs @@ -7,10 +7,8 @@ use core::{ use libk_mm::{address::PhysicalAddress, device::DeviceMemoryMapping}; -use crate::arch::{Platform, PlatformImpl}; - /// Offset applied to the physical kernel image when translating it into the virtual address space -pub const KERNEL_VIRT_OFFSET: usize = PlatformImpl::KERNEL_VIRT_OFFSET; +pub const KERNEL_VIRT_OFFSET: usize = kernel_arch::KERNEL_VIRT_OFFSET; /// Reads a value from an arbitrary physical address. /// diff --git a/kernel/tools/gentables/Cargo.toml b/kernel/tools/gentables/Cargo.toml deleted file mode 100644 index 40c25916..00000000 --- a/kernel/tools/gentables/Cargo.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "gentables" -version = "0.1.0" -edition = "2021" -authors = ["Mark Poliakov "] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -memtables = { workspace = true, features = ["all"] } - -bytemuck.workspace = true -bitflags.workspace = true - -thiserror = "1.0.48" -clap = { version = "4.4.2", features = ["derive"] } -elf = "0.7.2" diff --git a/kernel/tools/gentables/src/aarch64.rs b/kernel/tools/gentables/src/aarch64.rs deleted file mode 100644 index f42b2492..00000000 --- a/kernel/tools/gentables/src/aarch64.rs +++ /dev/null @@ -1,197 +0,0 @@ -use core::fmt; -use std::{ - collections::HashMap, - io::{Read, Seek}, - mem::offset_of, -}; - -use bitflags::bitflags; -use elf::{ - abi::{PF_W, PF_X, PT_LOAD}, - endian::AnyEndian, - ElfStream, -}; -use memtables::aarch64::{FixedTables, KERNEL_L3_COUNT}; - -use crate::{extract_symbols, GenData, GenError}; - -bitflags! { - #[derive(Clone, Copy)] - struct PageFlags: u64 { - const PRESENT = 1 << 0; - const ACCESS = 1 << 10; - const SH_INNER = 3 << 8; - const PAGE_ATTR_NORMAL = 0 << 2; - const AP_BOTH_READONLY = 3 << 6; - const TABLE = 1 << 1; - const PAGE = 1 << 1; - const UXN = 1 << 54; - const PXN = 1 << 53; - } -} - -impl PageFlags { - pub fn kernel_table() -> Self { - Self::PRESENT | Self::ACCESS | Self::SH_INNER | Self::PAGE_ATTR_NORMAL | Self::TABLE - } - - pub fn kernel_page() -> Self { - Self::PRESENT | Self::ACCESS | Self::SH_INNER | Self::PAGE_ATTR_NORMAL | Self::PAGE - } -} - -pub struct AArch64Builder { - elf: ElfStream, - data: GenData, - tables: FixedTables, - - l1i: usize, - l2i_start: usize, - l2i_end: usize, -} - -impl PageFlags { - fn from_elf(flags: u32) -> Self { - let mut out = Self::UXN | Self::PXN; - if flags & PF_X != 0 { - out.remove(Self::PXN); - } - if flags & PF_W == 0 { - out |= Self::AP_BOTH_READONLY; - } - out - } -} - -impl fmt::Display for PageFlags { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let x = if self.contains(Self::PXN) { '-' } else { 'x' }; - let w = if self.contains(Self::AP_BOTH_READONLY) { - '-' - } else { - 'w' - }; - write!(f, "r{}{}", w, x) - } -} - -const L1_SHIFT: u64 = 30; -const L2_SHIFT: u64 = 21; -const L3_SHIFT: u64 = 12; -const L2_ENTRY_SIZE: u64 = 1 << L2_SHIFT; -const L3_ENTRY_SIZE: u64 = 1 << L3_SHIFT; - -// TODO proper granularity -impl AArch64Builder { - pub fn new(elf: ElfStream, data: GenData) -> Result { - let l1i = (data.kernel_start >> L1_SHIFT) as usize & 0x1FF; - let l2i_start = (data.kernel_start >> L2_SHIFT) as usize & 0x1FF; - let l2i_end = ((data.kernel_end + L2_ENTRY_SIZE - 1) >> L2_SHIFT) as usize & 0x1FF; - - if l2i_end - l2i_start > KERNEL_L3_COUNT { - todo!() - } - - Ok(Self { - elf, - data, - - tables: FixedTables::zeroed(), - - l1i, - l2i_start, - l2i_end, - }) - } - - // TODO the build function is almost identical to x86-64 one, but with slight changes, so might - // wanna unify this later - pub fn build(mut self) -> Result<(FixedTables, u64, HashMap), GenError> { - assert_eq!(offset_of!(FixedTables, l1), 0); - - let l2_physical_address = - self.data.table_physical_address + offset_of!(FixedTables, l2) as u64; - - // L1 -> L2 - self.tables.l1.data[self.l1i] = l2_physical_address | PageFlags::kernel_table().bits(); - - // L2 -> L3s - for l2i in self.l2i_start..self.l2i_end { - let l3_table_index = l2i - self.l2i_start; - let l3_physical_address = self.data.table_physical_address - + (offset_of!(FixedTables, l3s) + 0x1000 * l3_table_index) as u64; - - println!("[{l2i}] -> {l3_physical_address:#x}"); - self.tables.l2.data[l2i] = l3_physical_address | PageFlags::kernel_table().bits(); - } - - let symbol_table = extract_symbols(&mut self.elf)?; - - for (i, segment) in self.elf.segments().into_iter().enumerate() { - if segment.p_type != PT_LOAD - || segment.p_vaddr != segment.p_paddr + self.data.kernel_virt_offset - { - continue; - } - - let aligned_virt_start = segment.p_vaddr & !(L3_ENTRY_SIZE - 1); - let aligned_virt_end = - (segment.p_vaddr + segment.p_memsz + L3_ENTRY_SIZE - 1) & !(L3_ENTRY_SIZE - 1); - let aligned_phys_start = segment.p_paddr & !(L3_ENTRY_SIZE - 1); - let count = (aligned_virt_end - aligned_virt_start) / 0x1000; - - let flags = PageFlags::from_elf(segment.p_flags); - - println!( - "{}: {:#x?} -> {:#x} {}", - i, - aligned_virt_start..aligned_virt_end, - aligned_phys_start, - flags - ); - Self::map_segment( - self.l2i_start, - &mut self.tables, - aligned_virt_start, - aligned_phys_start, - count as usize, - flags, - )?; - } - - Ok((self.tables, self.data.table_offset, symbol_table)) - } - - fn map_segment( - start_l2i: usize, - tables: &mut FixedTables, - vaddr_start: u64, - paddr_start: u64, - count: usize, - flags: PageFlags, - ) -> Result<(), GenError> { - for index in 0..count { - let vaddr = vaddr_start + index as u64 * L3_ENTRY_SIZE; - let paddr = paddr_start + index as u64 * L3_ENTRY_SIZE; - - let entry = paddr | (PageFlags::kernel_page() | flags).bits(); - - let l2i = ((vaddr >> L2_SHIFT) as usize & 0x1FF) - start_l2i; - let l3i = (vaddr >> L3_SHIFT) as usize & 0x1FF; - - let l3 = &mut tables.l3s[l2i]; - - if l3.data[l3i] != 0 { - if l3.data[l3i] != entry { - todo!(); - } else { - continue; - } - } - - l3.data[l3i] = entry; - } - - Ok(()) - } -} diff --git a/kernel/tools/gentables/src/main.rs b/kernel/tools/gentables/src/main.rs deleted file mode 100644 index a51495ac..00000000 --- a/kernel/tools/gentables/src/main.rs +++ /dev/null @@ -1,336 +0,0 @@ -use std::{ - collections::HashMap, - fs::{File, OpenOptions}, - io::{Read, Seek, SeekFrom, Write}, - ops::Range, - path::{Path, PathBuf}, - process::ExitCode, -}; - -use clap::Parser; -use elf::{ - abi::{EM_386, EM_AARCH64, EM_RISCV, EM_X86_64, PT_LOAD}, - endian::AnyEndian, - ElfStream, -}; -use memtables::any::AnyTables; -use riscv64::Riscv64Builder; -use thiserror::Error; - -use crate::{aarch64::AArch64Builder, x86_64::X8664Builder}; - -mod aarch64; -mod riscv64; -mod x86_64; - -#[derive(Error, Debug)] -pub enum GenError { - #[error("I/O error: {0}")] - IoError(#[from] std::io::Error), - #[error("ELF parse error: {0}")] - ElfParseError(#[from] elf::ParseError), - - #[error("Image's arhitecture is not supported")] - UnsupportedArchitecture, - #[error("Could not determine the kernel image address range (possibly incorrect segments?)")] - NoKernelImageRange, - #[error("Kernel image is too large: {0:#x?} ({1}B). Maximum size: {2}B")] - KernelTooLarge(Range, u64, u64), - #[error("Kernel image is missing a required symbol: {0:?}")] - MissingSymbol(&'static str), - #[error("Kernel image is missing a required section: {0:?}")] - MissingSection(&'static str), - #[error("Kernel image is missing a symbol table")] - MissingSymbolTable, - #[error("Incorrect tables section placement: {0:#x}")] - IncorrectTablesPlacement(u64), - #[error("Incorrect tables section size: got {0}, expected {1}")] - IncorrectTablesSize(u64, usize), - #[error("Incorrect tables section alignment: expected at least 4K, got {0}")] - IncorrectTablesAlign(u64), -} - -#[derive(Parser)] -struct Args { - image: PathBuf, - symbol_out: PathBuf, -} - -pub enum ImageHeader { - Riscv(u64), -} - -pub struct GenData { - pub kernel_start: u64, - pub kernel_end: u64, - - pub table_offset: u64, - pub table_physical_address: u64, - pub kernel_virt_offset: u64, -} - -pub struct BuiltTables { - pub image_size: u64, - pub image_header: Option, - pub tables: Option<(AnyTables, u64)>, - pub symbol_table: HashMap, -} - -fn kernel_image_range( - elf: &mut ElfStream, - kernel_virt_offset: u64, -) -> Result<(u64, u64), GenError> { - let mut start = u64::MAX; - let mut end = u64::MIN; - - for segment in elf.segments() { - if segment.p_type != PT_LOAD || segment.p_vaddr != segment.p_paddr + kernel_virt_offset { - continue; - } - - let aligned_start = segment.p_vaddr & !0xFFF; - let aligned_end = (segment.p_vaddr + segment.p_memsz + 0xFFF) & !0xFFF; - - if aligned_end > end { - end = aligned_end; - } - - if aligned_start < start { - start = aligned_start; - } - } - - if start < end { - Ok((start, end)) - } else { - Err(GenError::NoKernelImageRange) - } -} - -fn kernel_virt_offset(elf: &mut ElfStream) -> Result { - let (symtab, symstrtab) = elf - .symbol_table()? - .ok_or_else(|| GenError::MissingSection(".symtab"))?; - - for sym in symtab { - let name = symstrtab.get(sym.st_name as _)?; - - if name == "KERNEL_VIRT_OFFSET" { - // TODO symbol checks - return Ok(sym.st_value); - } - } - - Err(GenError::MissingSymbol("KERNEL_VIRT_OFFSET")) -} - -fn find_tables( - elf: &mut ElfStream, -) -> Result<(Option, u64, u64), GenError> { - let section_size = match elf.ehdr.e_machine { - EM_AARCH64 => size_of::(), - EM_X86_64 => size_of::(), - EM_RISCV => size_of::(), - _ => unimplemented!(), - }; - - let image_header = if let Some(text_entry) = elf.section_header_by_name(".text.entry")? { - let header = text_entry.clone(); - let section_offset = header.sh_offset; - let (data, _) = elf.section_data(&header)?; - if data.len() >= 64 { - let version = u32::from_le_bytes(data[32..36].try_into().unwrap()); - let magic0 = &data[48..56]; - let magic1 = &data[56..60]; - - match (version, magic0, magic1) { - (2, b"RISCV\x00\x00\x00", b"RSC\x05") => Some(ImageHeader::Riscv(section_offset)), - (_, _, _) => None, - } - } else { - None - } - } else { - None - }; - - let (shdrs, strtab) = elf.section_headers_with_strtab()?; - let strtab = strtab.ok_or_else(|| GenError::MissingSection(".strtab"))?; - - let mut tables = None; - - for shdr in shdrs { - let name = strtab.get(shdr.sh_name as _)?; - - if name == ".data.tables" { - if shdr.sh_size != section_size as _ { - return Err(GenError::IncorrectTablesSize(shdr.sh_size, section_size)); - } - if shdr.sh_addralign < 0x1000 { - return Err(GenError::IncorrectTablesAlign(shdr.sh_addralign)); - } - - // TODO section checks - tables = Some((shdr.sh_offset, shdr.sh_addr)); - } - } - - let (tables_offset, tables_addr) = tables.ok_or(GenError::MissingSection(".data.tables"))?; - - Ok((image_header, tables_offset, tables_addr)) -} - -fn extract_symbols( - elf: &mut ElfStream, -) -> Result, GenError> { - let mut table = HashMap::new(); - // let mut export_tables = HashSet::new(); - // let force_export = &[ - // "rust_begin_unwind", - // "__rust_alloc", - // "__rust_alloc_zeroed", - // "__rust_dealloc", - // "__rust_realloc", - // ]; - - // // Find all .export table indices - // let (shdrs, strtab) = elf.section_headers_with_strtab()?; - // let strtab = strtab.ok_or_else(|| GenError::MissingSection(".strtab"))?; - - // for (i, shdr) in shdrs.iter().enumerate() { - // if shdr.sh_type != elf::abi::SHT_PROGBITS { - // continue; - // } - - // let name = strtab.get(shdr.sh_name as _)?; - // if name.starts_with(".export.") { - // println!("Export from {:?}", name); - // export_tables.insert(i as u16); - // } - // } - - let (symtab, strtab) = elf.symbol_table()?.ok_or(GenError::MissingSymbolTable)?; - - // Only produce symbols from .export tables - - for sym in symtab { - if sym.st_vis() == elf::abi::STV_HIDDEN { - continue; - } - let name = strtab.get(sym.st_name as _)?; - // if export_tables.contains(&sym.st_shndx) || force_export.contains(&name) { - table.insert(name.to_owned(), sym.st_value as usize); - // } - } - - println!("{} exported symbols extracted", table.len()); - - Ok(table) -} - -fn into_any, U, V>((x, y, z): (T, U, V)) -> (AnyTables, U, V) { - (x.into(), y, z) -} - -fn build_tables(file: F) -> Result { - let mut elf = ElfStream::::open_stream(file)?; - - if elf.ehdr.e_machine == EM_386 { - // Locate symbol table - let symbol_table = extract_symbols(&mut elf)?; - return Ok(BuiltTables { - image_size: 0, - image_header: None, - tables: None, - symbol_table, - }); - } - - let kernel_virt_offset = kernel_virt_offset(&mut elf)?; - let (kernel_start, kernel_end) = kernel_image_range(&mut elf, kernel_virt_offset)?; - let (image_header, table_offset, table_virt_addr) = find_tables(&mut elf)?; - let table_physical_address = table_virt_addr - .checked_sub(kernel_virt_offset) - .ok_or_else(|| GenError::IncorrectTablesPlacement(table_virt_addr))?; - - println!("Kernel image range: {:#x?}", kernel_start..kernel_end); - println!("KERNEL_VIRT_OFFSET = {:#x}", kernel_virt_offset); - - let gen_data = GenData { - kernel_virt_offset, - kernel_start, - kernel_end, - table_offset, - table_physical_address, - }; - - let (tables, table_offset, symbol_table) = match elf.ehdr.e_machine { - EM_X86_64 => X8664Builder::new(elf, gen_data)?.build().map(into_any), - EM_AARCH64 => AArch64Builder::new(elf, gen_data)?.build().map(into_any), - EM_RISCV => Riscv64Builder::new(elf, gen_data)?.build().map(into_any), - _ => todo!(), - }?; - - Ok(BuiltTables { - image_size: kernel_end - kernel_start, - image_header, - tables: Some((tables, table_offset)), - symbol_table, - }) -} - -fn write_tables( - mut file: F, - offset: u64, - tables: AnyTables, -) -> Result<(), GenError> { - file.seek(SeekFrom::Start(offset))?; - file.write_all(tables.as_bytes())?; - Ok(()) -} - -fn write_symbol_table( - out: impl AsRef, - table: HashMap, -) -> Result<(), GenError> { - let mut file = File::create(out)?; - - for (name, value) in table { - let len: u32 = name.len().try_into().unwrap(); - let value: u64 = value.try_into().unwrap(); - - file.write_all(&len.to_le_bytes())?; - file.write_all(name.as_bytes())?; - file.write_all(&value.to_le_bytes())?; - } - - Ok(()) -} - -fn gentables(image: impl AsRef, symbol_out: impl AsRef) -> Result<(), GenError> { - let mut file = OpenOptions::new() - .read(true) - .write(true) - .truncate(false) - .open(image)?; - - let built = build_tables(&mut file)?; - write_symbol_table(symbol_out, built.symbol_table)?; - if let Some((tables, file_offset)) = built.tables { - write_tables(file, file_offset, tables)?; - } - - Ok(()) -} - -fn main() -> ExitCode { - let args = Args::parse(); - - match gentables(&args.image, &args.symbol_out) { - Ok(()) => ExitCode::SUCCESS, - Err(err) => { - eprintln!("{}: {}", args.image.display(), err); - ExitCode::FAILURE - } - } -} diff --git a/kernel/tools/gentables/src/riscv64.rs b/kernel/tools/gentables/src/riscv64.rs deleted file mode 100644 index 2c4bdafd..00000000 --- a/kernel/tools/gentables/src/riscv64.rs +++ /dev/null @@ -1,172 +0,0 @@ -use std::{ - collections::HashMap, - io::{Read, Seek}, - mem::offset_of, -}; - -use elf::{ - abi::{PF_W, PF_X, PT_LOAD}, - endian::AnyEndian, - ElfStream, -}; -use memtables::riscv64::{FixedTables, PageAttributes, KERNEL_L3_COUNT}; - -use crate::{extract_symbols, GenData, GenError}; - -pub struct Riscv64Builder { - elf: ElfStream, - data: GenData, - tables: FixedTables, - - l1i_lower: usize, - l1i: usize, - l2i_start: usize, - l2i_end: usize, -} - -const L1_SHIFT: usize = 30; -const L1_PAGE_SIZE: usize = 1 << L1_SHIFT; -const L2_SHIFT: usize = 21; -const L2_PAGE_SIZE: usize = 1 << L2_SHIFT; -const L3_SHIFT: usize = 12; -const L3_PAGE_SIZE: usize = 1 << L3_SHIFT; - -fn segment_attributes(f: u32) -> PageAttributes { - let mut attrs = PageAttributes::R | PageAttributes::A | PageAttributes::D; - if f & PF_W != 0 { - attrs |= PageAttributes::W; - } - if f & PF_X != 0 { - attrs |= PageAttributes::X; - } - attrs -} - -fn shift_pfn(physical: u64) -> u64 { - physical >> 2 -} - -impl Riscv64Builder { - pub fn new(elf: ElfStream, data: GenData) -> Result { - assert_eq!(data.kernel_virt_offset & (L1_PAGE_SIZE as u64 - 1), 0); - - let l1i = (data.kernel_start >> L1_SHIFT) as usize & 0x1FF; - let l1i_lower = - ((data.kernel_start - data.kernel_virt_offset) >> L1_SHIFT) as usize & 0x1FF; - - let end_l1i = ((data.kernel_end + L1_PAGE_SIZE as u64) >> L1_SHIFT) as usize & 0x1FF; - if end_l1i < l1i || end_l1i - l1i > 1 { - // TODO return error - panic!("Kernel image crosses a 1GiB boundary"); - } - let l2i_start = (data.kernel_start >> L2_SHIFT) as usize & 0x1FF; - let l2i_end = ((data.kernel_end + L2_PAGE_SIZE as u64 - 1) >> L2_SHIFT) as usize & 0x1FF; - assert!(l2i_end >= l2i_start); - if l2i_end - l2i_start > KERNEL_L3_COUNT { - panic!(); - } - - Ok(Self { - elf, - data, - tables: FixedTables::zeroed(), - - l1i_lower, - l1i, - l2i_start, - l2i_end, - }) - } - - pub fn build(mut self) -> Result<(FixedTables, u64, HashMap), GenError> { - assert_eq!(offset_of!(FixedTables, l1), 0); - - let l2_physical_address = - self.data.table_physical_address + offset_of!(FixedTables, kernel_l2) as u64; - - // L1 -> L2 - self.tables.l1.data[self.l1i_lower] = - shift_pfn(l2_physical_address) | PageAttributes::V.bits(); - self.tables.l1.data[self.l1i] = shift_pfn(l2_physical_address) | PageAttributes::V.bits(); - - // L2 -> L3s - for l2i in self.l2i_start..self.l2i_end { - let l3_table_index = l2i - self.l2i_start; - let l3_physical_address = self.data.table_physical_address - + offset_of!(FixedTables, kernel_l3s) as u64 - + (l3_table_index * 0x1000) as u64; - - self.tables.kernel_l2.data[l2i] = - shift_pfn(l3_physical_address) | PageAttributes::V.bits(); - } - - let symbol_table = extract_symbols(&mut self.elf)?; - - for (i, segment) in self.elf.segments().into_iter().enumerate() { - if segment.p_type != PT_LOAD - || segment.p_vaddr != segment.p_paddr + self.data.kernel_virt_offset - { - continue; - } - - let aligned_virt_start = segment.p_vaddr & !(L3_PAGE_SIZE as u64 - 1); - let aligned_virt_end = (segment.p_vaddr + segment.p_memsz + L3_PAGE_SIZE as u64 - 1) - & !(L3_PAGE_SIZE as u64 - 1); - let aligned_phys_start = segment.p_paddr & !(L3_PAGE_SIZE as u64 - 1); - let count = (aligned_virt_end - aligned_virt_start) / 0x1000; - - let attrs = segment_attributes(segment.p_flags); - - println!( - "{}: {:#x?} -> {:#x} {}", - i, - aligned_virt_start..aligned_virt_end, - aligned_phys_start, - attrs - ); - Self::map_segment( - self.l2i_start, - &mut self.tables, - aligned_virt_start, - aligned_phys_start, - count as usize, - attrs, - )?; - } - - Ok((self.tables, self.data.table_offset, symbol_table)) - } - - fn map_segment( - start_l2i: usize, - tables: &mut FixedTables, - vaddr_start: u64, - paddr_start: u64, - count: usize, - flags: PageAttributes, - ) -> Result<(), GenError> { - for index in 0..count { - let vaddr = vaddr_start + (index * L3_PAGE_SIZE) as u64; - let paddr = paddr_start + (index * L3_PAGE_SIZE) as u64; - - let entry = shift_pfn(paddr) | (PageAttributes::V | flags).bits(); - - let l2i = ((vaddr >> L2_SHIFT) as usize & 0x1FF) - start_l2i; - let l3i = (vaddr >> L3_SHIFT) as usize & 0x1FF; - - let l3 = &mut tables.kernel_l3s[l2i]; - - if l3.data[l3i] != 0 { - if l3.data[l3i] != entry { - todo!(); - } else { - continue; - } - } - - l3.data[l3i] = entry; - } - - Ok(()) - } -} diff --git a/kernel/tools/gentables/src/x86_64.rs b/kernel/tools/gentables/src/x86_64.rs deleted file mode 100644 index b6562730..00000000 --- a/kernel/tools/gentables/src/x86_64.rs +++ /dev/null @@ -1,195 +0,0 @@ -use core::fmt; -use std::{ - collections::HashMap, - io::{Read, Seek}, - mem::offset_of, -}; - -use bitflags::bitflags; -use elf::{abi::PT_LOAD, endian::AnyEndian, ElfStream}; -use memtables::x86_64::{FixedTables, KERNEL_L3_COUNT}; - -use crate::{extract_symbols, GenData, GenError}; - -bitflags! { - #[derive(Clone, Copy)] - struct PageFlags: u64 { - const PRESENT = 1 << 0; - const WRITABLE = 1 << 1; - // const NX = 1 << 63; - } -} - -pub struct X8664Builder { - elf: ElfStream, - data: GenData, - tables: FixedTables, - - l0i: usize, - l1i: usize, - start_l2i: usize, - end_l2i: usize, -} - -impl PageFlags { - fn from_elf(_flags: u32) -> Self { - let mut out = Self::empty(); - // if flags & PF_W != 0 { - out |= Self::WRITABLE; - // } - // if flags & PF_X == 0 { - // // out |= Self::NX; - // } - out - } -} - -impl fmt::Display for PageFlags { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "r{}{}", - if self.contains(Self::WRITABLE) { - 'w' - } else { - '-' - }, - 'x' // if self.contains(Self::NX) { '-' } else { 'x' } - ) - } -} - -impl X8664Builder { - pub fn new(elf: ElfStream, data: GenData) -> Result { - let l2_aligned_start = data.kernel_start & !0x1FFFFF; - let l2_aligned_end = (data.kernel_end + 0x1FFFFF) & !0x1FFFFF; - - if l2_aligned_end <= l2_aligned_start { - todo!(); - } - - if (l2_aligned_end - l2_aligned_start) as usize >= KERNEL_L3_COUNT * 0x200000 { - return Err(GenError::KernelTooLarge( - l2_aligned_start..l2_aligned_end, - l2_aligned_end - l2_aligned_start, - (KERNEL_L3_COUNT * 0x20000) as u64, - )); - } - - let l0i = (data.kernel_start >> 39) as usize & 0x1FF; - let l1i = (data.kernel_start >> 30) as usize & 0x1FF; - let start_l2i = (l2_aligned_start >> 21) as usize & 0x1FF; - let end_l2i = (l2_aligned_end >> 21) as usize & 0x1FF; - - Ok(Self { - elf, - data, - tables: FixedTables::zeroed(), - - l0i, - l1i, - start_l2i, - end_l2i, - }) - } - - pub fn build(mut self) -> Result<(FixedTables, u64, HashMap), GenError> { - assert_eq!(offset_of!(FixedTables, l0), 0); - let l1_physical_address = - self.data.table_physical_address + offset_of!(FixedTables, kernel_l1) as u64; - let l2_physical_address = - self.data.table_physical_address + offset_of!(FixedTables, kernel_l2) as u64; - - // L0 -> L1 - self.tables.l0.data[self.l0i] = - l1_physical_address | (PageFlags::PRESENT | PageFlags::WRITABLE).bits(); - - // L1 -> L2 - self.tables.kernel_l1.data[self.l1i] = - l2_physical_address | (PageFlags::PRESENT | PageFlags::WRITABLE).bits(); - - // L2 -> L3s - for l2i in self.start_l2i..self.end_l2i { - let l3_table_index = l2i - self.start_l2i; - let l3_physical_address = self.data.table_physical_address - + (offset_of!(FixedTables, kernel_l3s) + 0x1000 * l3_table_index) as u64; - - self.tables.kernel_l2.data[l2i] = - l3_physical_address | (PageFlags::PRESENT | PageFlags::WRITABLE).bits(); - } - - // Locate symbol table - let symbol_table = extract_symbols(&mut self.elf)?; - - for (i, segment) in self.elf.segments().into_iter().enumerate() { - if segment.p_type != PT_LOAD - || segment.p_vaddr != segment.p_paddr + self.data.kernel_virt_offset - { - continue; - } - - let aligned_virt_start = segment.p_vaddr & !0xFFF; - let aligned_virt_end = (segment.p_vaddr + segment.p_memsz + 0xFFF) & !0xFFF; - let aligned_phys_start = segment.p_paddr & !0xFFF; - let count = (aligned_virt_end - aligned_virt_start) / 0x1000; - - let flags = PageFlags::from_elf(segment.p_flags); - - println!( - "{}: {:#x?} -> {:#x} {}", - i, - aligned_virt_start..aligned_virt_end, - aligned_phys_start, - flags - ); - - Self::map_segment( - self.start_l2i, - &mut self.tables, - aligned_virt_start, - aligned_phys_start, - count as usize, - flags, - )?; - } - - Ok((self.tables, self.data.table_offset, symbol_table)) - } - - fn map_segment( - l2i_offset: usize, - tables: &mut FixedTables, - vaddr: u64, - paddr: u64, - count: usize, - flags: PageFlags, - ) -> Result<(), GenError> { - for index in 0..count { - let address = vaddr + index as u64 * 0x1000; - let page = paddr + index as u64 * 0x1000; - - let entry = page | (PageFlags::PRESENT | flags).bits(); - - let l2i = ((address >> 21) as usize & 0x1FF) - l2i_offset; - let l3i = (address >> 12) as usize & 0x1FF; - - let l3 = &mut tables.kernel_l3s[l2i]; - - if l3.data[l3i] != 0 { - if l3.data[l3i] != entry { - eprintln!( - "{:#x} is already mapped to {:#x}, tried to map to {:#x}", - address, l3.data[l3i], page - ); - todo!(); - } else { - continue; - } - } - - l3.data[l3i] = entry; - } - - Ok(()) - } -} diff --git a/xtask/src/build/cargo.rs b/xtask/src/build/cargo.rs index 2fa6c997..f71d3237 100644 --- a/xtask/src/build/cargo.rs +++ b/xtask/src/build/cargo.rs @@ -1,7 +1,7 @@ use std::{ffi::OsStr, path::Path, process::Command}; use crate::{ - env::{Arch, Board, BuildEnv, Profile}, + env::{BuildEnv, Profile}, error::Error, }; @@ -113,9 +113,9 @@ impl<'e> CargoBuilder<'e> { command.env( "RUSTFLAGS", format!( - "-C link-arg=-T{}/etc/ld/{}", + "-C link-arg=-T{}/etc/ld/{}.ld", env.workspace_root.display(), - env.kernel_linker_script, + env.kernel_triple ), ); command.arg("+nightly").arg(arg); @@ -124,28 +124,11 @@ impl<'e> CargoBuilder<'e> { command.arg("-v"); } - let target_spec_arg = format!( - "--target={}/etc/{}-unknown-none.json", + command.arg(format!( + "--target={}/etc/{}.json", env.workspace_root.display(), - env.arch.name() - ); - let target_dir_arg = format!( - "--target-dir={}", - env.workspace_root - .join("target") - .join(env.kernel_triple) - .display() - ); - - command.arg(target_spec_arg); - - command.arg(target_dir_arg); - - if arg != "clippy" && arg != "check" { - let artifact_dir_arg = - format!("--artifact-dir={}", env.kernel_output_dir.display()); - command.arg(artifact_dir_arg); - } + env.kernel_triple + )); command.args([ "-Z", @@ -153,22 +136,6 @@ impl<'e> CargoBuilder<'e> { "-Zunstable-options", ]); - match (env.arch, env.board) { - (Arch::aarch64, Board::virt | Board::default) => { - command.arg("--features=aarch64_board_virt"); - } - (Arch::aarch64, Board::raspi4b) => { - command.arg("--features=aarch64_board_raspi4b"); - } - (Arch::riscv64, Board::virt | Board::default) => { - command.arg("--features=riscv64_board_virt"); - } - (Arch::riscv64, Board::jh7110) => { - command.arg("--features=riscv64_board_jh7110"); - } - (_, _) => (), - }; - if env.profile == Profile::Release { command.arg("--release"); } diff --git a/xtask/src/build/mod.rs b/xtask/src/build/mod.rs index 7f007b11..8a57d9ee 100644 --- a/xtask/src/build/mod.rs +++ b/xtask/src/build/mod.rs @@ -1,8 +1,4 @@ -use std::{ - fs, - path::{Path, PathBuf}, - process::Command, -}; +use std::{fs, path::PathBuf, process::Command}; use crate::{ build::cargo::CargoBuilder, @@ -39,23 +35,13 @@ impl CheckAction { pub struct ToolsBuilt(pub PathBuf); pub struct KernelBuilt(pub PathBuf); -pub struct KernelProcessed(pub KernelBuilt); pub struct KernelBin(pub PathBuf); pub struct InitrdGenerated(pub PathBuf); pub struct ImageBuilt(pub PathBuf); pub enum AllBuilt { Riscv64(KernelBin, InitrdGenerated), + AArch64(KernelBin, InitrdGenerated), X86_64(ImageBuilt), - AArch64(KernelProcessed, InitrdGenerated), - I686(ImageBuilt), -} - -pub fn build_kernel_tools(env: &BuildEnv, _: AllOk) -> Result { - log::info!("Building kernel tools"); - CargoBuilder::Host(env.verbose).build("kernel/tools/gentables")?; - Ok(ToolsBuilt( - env.workspace_root.join("target/debug/gentables"), - )) } pub fn build_kernel(env: &BuildEnv, _: AllOk) -> Result { @@ -64,17 +50,13 @@ pub fn build_kernel(env: &BuildEnv, _: AllOk) -> Result { Ok(KernelBuilt(env.kernel_output_dir.join("yggdrasil-kernel"))) } -pub fn make_kernel_bin( - env: &BuildEnv, - kernel: KernelProcessed, - _: AllOk, -) -> Result { +pub fn make_kernel_bin(env: &BuildEnv, kernel: KernelBuilt, _: AllOk) -> Result { log::info!("Building yggdrasil-kernel.bin"); let kernel_bin = env.kernel_output_dir.join("yggdrasil-kernel.bin"); let status = Command::new("llvm-objcopy") .args(["-O", "binary"]) - .arg(kernel.0 .0) + .arg(kernel.0) .arg(&kernel_bin) .status()?; if !status.success() { @@ -84,32 +66,13 @@ pub fn make_kernel_bin( Ok(KernelBin(kernel_bin)) } -pub fn generate_kernel_tables( - symbol_path: impl AsRef, - kernel: KernelBuilt, - tools: ToolsBuilt, -) -> Result { - log::info!("Generating kernel MMU translation tables"); - let status = Command::new(tools.0) - .arg(kernel.0.clone()) - .arg(symbol_path.as_ref()) - .status()?; - if status.success() { - Ok(KernelProcessed(kernel)) - } else { - Err(Error::GentablesError) - } -} - pub fn build_all(env: &BuildEnv) -> Result { log::debug!("Environment: {:#?}", env); let check = check::check_build_env(env.arch)?; // Kernel stuff - let tools = build_kernel_tools(env, check)?; let kernel = build_kernel(env, check)?; - let kernel = generate_kernel_tables(&env.kernel_symbol_file, kernel, tools)?; // let modules = match env.arch { // Arch::i686 => Vec::new(), @@ -128,7 +91,7 @@ pub fn build_all(env: &BuildEnv) -> Result { // Build target-specific image let image = match env.arch { Arch::riscv64 => AllBuilt::Riscv64(make_kernel_bin(env, kernel, check)?, initrd), - Arch::aarch64 => AllBuilt::AArch64(kernel, initrd), + Arch::aarch64 => AllBuilt::AArch64(make_kernel_bin(env, kernel, check)?, initrd), Arch::x86_64 => AllBuilt::X86_64(x86_64::build_image(env, kernel, initrd)?), }; diff --git a/xtask/src/build/userspace.rs b/xtask/src/build/userspace.rs index 904bb1d0..f7dc36a3 100644 --- a/xtask/src/build/userspace.rs +++ b/xtask/src/build/userspace.rs @@ -167,8 +167,6 @@ fn build_rootfs, D: AsRef>( util::copy_file(src, rootfs_dir.join(dst))?; } - util::copy_file(&env.kernel_symbol_file, rootfs_dir.join("kernel.sym"))?; - // Copy /etc util::copy_dir_recursive(user_dir.join("etc"), rootfs_dir.join("etc"))?; diff --git a/xtask/src/build/x86_64.rs b/xtask/src/build/x86_64.rs index a30cf20b..805631f9 100644 --- a/xtask/src/build/x86_64.rs +++ b/xtask/src/build/x86_64.rs @@ -6,9 +6,14 @@ use std::{ use fscommon::BufStream; -use crate::{build::cargo::CargoBuilder, env::BuildEnv, error::Error, util}; +use crate::{ + build::{cargo::CargoBuilder, KernelBuilt}, + env::BuildEnv, + error::Error, + util, +}; -use super::{ImageBuilt, InitrdGenerated, KernelProcessed}; +use super::{ImageBuilt, InitrdGenerated}; pub struct YbootBuilt(PathBuf); @@ -44,7 +49,7 @@ fn copy_into_fat( fn build_uefi_image( env: &BuildEnv, yboot: YbootBuilt, - kernel: KernelProcessed, + kernel: KernelBuilt, initrd: InitrdGenerated, ) -> Result { log::info!("Building x86-64 UEFI image"); @@ -80,7 +85,7 @@ fn build_uefi_image( let boot_dir = root_dir.create_dir("EFI")?.create_dir("Boot")?; copy_into_fat(&boot_dir, &yboot.0, "BootX64.efi")?; - copy_into_fat(&root_dir, &kernel.0 .0, "kernel.elf")?; + copy_into_fat(&root_dir, &kernel.0, "kernel.elf")?; copy_into_fat(&root_dir, &initrd.0, "initrd.img")?; if yboot_cfg.exists() { copy_into_fat(&root_dir, &yboot_cfg, "yboot.cfg")?; @@ -93,7 +98,7 @@ fn build_uefi_image( pub fn build_image( env: &BuildEnv, - kernel: KernelProcessed, + kernel: KernelBuilt, initrd: InitrdGenerated, ) -> Result { let yboot = build_yboot(env)?; diff --git a/xtask/src/env.rs b/xtask/src/env.rs index 1f513845..6d13cf22 100644 --- a/xtask/src/env.rs +++ b/xtask/src/env.rs @@ -99,14 +99,12 @@ pub struct BuildEnv { pub arch: Arch, pub board: Board, pub kernel_triple: &'static str, - pub kernel_linker_script: String, pub host_triple: String, pub workspace_root: PathBuf, pub kernel_output_dir: PathBuf, pub userspace_output_dir: PathBuf, - pub kernel_symbol_file: PathBuf, pub ports_sysroot: PathBuf, } @@ -136,21 +134,10 @@ impl BuildEnv { board: Board, workspace_root: PathBuf, ) -> Self { - let kernel_triple = match (arch, board) { - (Arch::aarch64, Board::virt | Board::default) => "aarch64-unknown-qemu", - (Arch::riscv64, Board::virt | Board::default) => "riscv64-unknown-qemu", - (Arch::riscv64, Board::jh7110) => "riscv64-unknown-jh7110", - (Arch::aarch64, Board::raspi4b) => "aarch64-unknown-raspi4b", - (Arch::x86_64, Board::default) => "x86_64-unknown-none", - _ => { - log::error!("Invalid arch/board combination: {arch:?}/{board:?}"); - panic!(); - } - }; - let kernel_linker_script = match arch { - Arch::aarch64 => format!("arm/{kernel_triple}.ld"), - Arch::riscv64 => format!("riscv/{kernel_triple}.ld"), - Arch::x86_64 => format!("x86/{kernel_triple}.ld"), + let kernel_triple = match arch { + Arch::aarch64 => "aarch64-unknown-none", + Arch::riscv64 => "riscv64-unknown-none", + Arch::x86_64 => "x86_64-unknown-none", }; let kernel_output_dir = workspace_root.join(format!("target/{}/{}", kernel_triple, profile.dir())); @@ -159,7 +146,6 @@ impl BuildEnv { arch.name(), profile.dir() )); - let kernel_symbol_file = kernel_output_dir.join("symbols.dat"); let host = env!("TARGET"); let ports_sysroot = workspace_root.join( @@ -177,12 +163,10 @@ impl BuildEnv { arch, board, kernel_triple, - kernel_linker_script, host_triple: host.into(), workspace_root, - kernel_symbol_file, kernel_output_dir, userspace_output_dir, diff --git a/xtask/src/qemu.rs b/xtask/src/qemu.rs index 25a52193..6d518dc6 100644 --- a/xtask/src/qemu.rs +++ b/xtask/src/qemu.rs @@ -7,14 +7,13 @@ use std::{ use qemu::{ aarch64, device::{QemuDevice, QemuDrive, QemuNic, QemuSerialTarget}, - i386, riscv64, x86_64, Qemu, + riscv64, x86_64, Qemu, }; use crate::{ - build::{self, AllBuilt, ImageBuilt, InitrdGenerated, KernelBin, KernelBuilt, KernelProcessed}, + build::{self, AllBuilt, ImageBuilt, InitrdGenerated, KernelBin}, env::{Board, BuildEnv}, error::Error, - util::run_external_command, }; #[derive(Debug, Default, serde::Deserialize, serde::Serialize)] @@ -145,19 +144,6 @@ impl From for QemuDrive { } } -fn make_kernel_bin, D: AsRef>(src: S, dst: D) -> Result<(), Error> { - run_external_command( - "llvm-objcopy", - [ - "-O".as_ref(), - "binary".as_ref(), - src.as_ref().as_os_str(), - dst.as_ref().as_os_str(), - ], - false, - ) -} - // TODO device settings fn run_aarch64( @@ -245,31 +231,6 @@ fn run_x86_64( Ok(qemu.into_command()) } -fn run_i686( - config: &QemuConfig, - qemu_bin: Option, - devices: Vec, - image: PathBuf, -) -> Result { - let mut qemu = Qemu::new_i386(); - if let Some(qemu_bin) = qemu_bin { - qemu.override_qemu(qemu_bin); - } - qemu.with_serial(QemuSerialTarget::MonStdio) - .with_cpu(i386::Cpu::Host { - enable_kvm: config.machine.i686.enable_kvm, - }) - .with_machine(i386::Machine::Q35) - .with_cdrom(&image) - .with_memory_megabytes(config.machine.i686.memory); - - for device in devices { - qemu.with_device(device); - } - - Ok(qemu.into_command()) -} - fn run_riscv64( config: &QemuConfig, env: &BuildEnv, @@ -371,8 +332,6 @@ pub fn run( ) -> Result<(), Error> { let config = load_qemu_config(env.workspace_root.join("qemu.toml"))?; - let kernel_output_dir = env.kernel_output_dir.clone(); - let kernel_bin = kernel_output_dir.join("kernel.bin"); // Rebuild the image let built = build::build_all(&env)?; @@ -383,12 +342,10 @@ pub fn run( AllBuilt::Riscv64(KernelBin(kernel), InitrdGenerated(initrd)) => { run_riscv64(&config, &env, qemu, devices, kernel, initrd)? } - AllBuilt::AArch64(KernelProcessed(KernelBuilt(kernel)), InitrdGenerated(initrd)) => { - make_kernel_bin(kernel, &kernel_bin)?; - run_aarch64(&config, &env, qemu, devices, kernel_bin, initrd)? + AllBuilt::AArch64(KernelBin(kernel), InitrdGenerated(initrd)) => { + run_aarch64(&config, &env, qemu, devices, kernel, initrd)? } AllBuilt::X86_64(ImageBuilt(image)) => run_x86_64(&config, qemu, devices, image)?, - AllBuilt::I686(ImageBuilt(image)) => run_i686(&config, qemu, devices, image)?, }; command.args(extra_args);