From c6e6ccd2a48ed82b9401ac36fbd66d844fcc5a1f Mon Sep 17 00:00:00 2001 From: Andre Richter Date: Sun, 27 Jan 2019 21:41:09 +0100 Subject: [PATCH] Add code for global println lesson --- 0E_global_println/.cargo/config | 6 + 0E_global_println/Cargo.lock | 55 ++++ 0E_global_println/Cargo.toml | 13 + 0E_global_println/Makefile | 65 +++++ 0E_global_println/README.md | 28 ++ 0E_global_println/kernel8 | Bin 0 -> 88168 bytes 0E_global_println/kernel8.img | Bin 0 -> 11093 bytes 0E_global_println/link.ld | 57 ++++ 0E_global_println/raspi3_boot/Cargo.toml | 10 + 0E_global_println/raspi3_boot/src/lib.rs | 130 +++++++++ 0E_global_println/src/delays.rs | 37 +++ 0E_global_println/src/devices.rs | 26 ++ 0E_global_println/src/devices/hw.rs | 31 ++ 0E_global_println/src/devices/hw/gpio.rs | 120 ++++++++ .../src/devices/hw/pl011_uart.rs | 276 ++++++++++++++++++ .../src/devices/hw/videocore_mbox.rs | 164 +++++++++++ 0E_global_println/src/devices/virt.rs | 27 ++ 0E_global_println/src/devices/virt/console.rs | 136 +++++++++ 0E_global_println/src/macros.rs | 49 ++++ 0E_global_println/src/main.rs | 106 +++++++ 0E_global_println/src/memory.rs | 113 +++++++ 0E_global_println/src/memory/mmu.rs | 229 +++++++++++++++ 0E_global_println/src/sync.rs | 62 ++++ 23 files changed, 1740 insertions(+) create mode 100644 0E_global_println/.cargo/config create mode 100644 0E_global_println/Cargo.lock create mode 100644 0E_global_println/Cargo.toml create mode 100644 0E_global_println/Makefile create mode 100644 0E_global_println/README.md create mode 100755 0E_global_println/kernel8 create mode 100755 0E_global_println/kernel8.img create mode 100644 0E_global_println/link.ld create mode 100644 0E_global_println/raspi3_boot/Cargo.toml create mode 100644 0E_global_println/raspi3_boot/src/lib.rs create mode 100644 0E_global_println/src/delays.rs create mode 100644 0E_global_println/src/devices.rs create mode 100644 0E_global_println/src/devices/hw.rs create mode 100644 0E_global_println/src/devices/hw/gpio.rs create mode 100644 0E_global_println/src/devices/hw/pl011_uart.rs create mode 100644 0E_global_println/src/devices/hw/videocore_mbox.rs create mode 100644 0E_global_println/src/devices/virt.rs create mode 100644 0E_global_println/src/devices/virt/console.rs create mode 100644 0E_global_println/src/macros.rs create mode 100644 0E_global_println/src/main.rs create mode 100644 0E_global_println/src/memory.rs create mode 100644 0E_global_println/src/memory/mmu.rs create mode 100644 0E_global_println/src/sync.rs diff --git a/0E_global_println/.cargo/config b/0E_global_println/.cargo/config new file mode 100644 index 00000000..d7fb2ba3 --- /dev/null +++ b/0E_global_println/.cargo/config @@ -0,0 +1,6 @@ +[target.aarch64-unknown-none] +rustflags = [ + "-C", "link-arg=-Tlink.ld", + "-C", "target-feature=-fp-armv8", + "-C", "target-cpu=cortex-a53", +] diff --git a/0E_global_println/Cargo.lock b/0E_global_println/Cargo.lock new file mode 100644 index 00000000..db059c6f --- /dev/null +++ b/0E_global_println/Cargo.lock @@ -0,0 +1,55 @@ +[[package]] +name = "cortex-a" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "register 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "kernel8" +version = "0.1.0" +dependencies = [ + "cortex-a 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "raspi3_boot 0.1.0", + "register 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "panic-abort" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "r0" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "raspi3_boot" +version = "0.1.0" +dependencies = [ + "cortex-a 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "panic-abort 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "register" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "tock-registers 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tock-registers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum cortex-a 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "97867bac786c0a2912f7df981bdb8b6ea109a2422c22b37faf651d558a054453" +"checksum panic-abort 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2c14a66511ed17b6a8b4256b868d7fd207836d891db15eea5195dbcaf87e630f" +"checksum r0 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a38df5b15c8d5c7e8654189744d8e396bddc18ad48041a500ce52d6948941f" +"checksum register 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a0f44a6dc9a98359515541a0c46ef4e3630a30879c1d7a4038f31dd533570bfb" +"checksum tock-registers 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c758f5195a2e0df9d9fecf6f506506b2766ff74cf64db1e995c87e2761a5c3e2" diff --git a/0E_global_println/Cargo.toml b/0E_global_println/Cargo.toml new file mode 100644 index 00000000..6d1bfce0 --- /dev/null +++ b/0E_global_println/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "kernel8" +version = "0.1.0" +authors = ["Andre Richter "] +edition = "2018" + +[dependencies] +raspi3_boot = { path = "raspi3_boot" } +cortex-a = "2.4.0" +register = "0.3.2" + +[package.metadata.cargo-xbuild] +sysroot_path = "../xbuild_sysroot" diff --git a/0E_global_println/Makefile b/0E_global_println/Makefile new file mode 100644 index 00000000..750ad650 --- /dev/null +++ b/0E_global_println/Makefile @@ -0,0 +1,65 @@ +# +# MIT License +# +# Copyright (c) 2018-2019 Andre Richter +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# + +TARGET = aarch64-unknown-none + +SOURCES = $(wildcard **/*.rs) $(wildcard **/*.S) link.ld + +OBJCOPY = cargo objcopy -- +OBJCOPY_PARAMS = --strip-all -O binary + +UTILS_CONTAINER = andrerichter/raspi3-utils +DOCKER_CMD = docker run -it --rm -v $(shell pwd):/work -w /work +DOCKER_TTY = --privileged -v /dev:/dev +QEMU_CMD = qemu-system-aarch64 -M raspi3 -kernel kernel8.img +RASPBOOT_CMD = raspbootcom /dev/ttyUSB0 kernel8.img + +.PHONY: all qemu raspboot clippy clean objdump nm + +all: clean kernel8.img + +target/$(TARGET)/release/kernel8: $(SOURCES) + cargo xbuild --target=$(TARGET) --release + +kernel8.img: target/$(TARGET)/release/kernel8 + cp $< . + $(OBJCOPY) $(OBJCOPY_PARAMS) $< kernel8.img + +qemu: all + $(DOCKER_CMD) $(UTILS_CONTAINER) $(QEMU_CMD) -serial stdio + +raspboot: all + $(DOCKER_CMD) $(DOCKER_TTY) $(UTILS_CONTAINER) $(RASPBOOT_CMD) + +clippy: + cargo xclippy --target=$(TARGET) + +clean: + cargo clean + +objdump: + cargo objdump --target $(TARGET) -- -disassemble -print-imm-hex kernel8 + +nm: + cargo nm --target $(TARGET) -- kernel8 | sort diff --git a/0E_global_println/README.md b/0E_global_println/README.md new file mode 100644 index 00000000..5dc02a5c --- /dev/null +++ b/0E_global_println/README.md @@ -0,0 +1,28 @@ +# Tutorial 0E - Global `println!` + +Coming soon! + +This lesson will teach about: +- Restructuring the current codebase. +- Realizing global println! and print! macros by reusing macros from the Rust + standard library. +- The NullLock, a wrapper that allows using global static variables without + explicit need for `unsafe {}` code. It is a teaching concept that is only + valid in single-threaded IRQ-disabled environments. However, it already lays + the groundwork for the introduction of proper locking mechanisms, e.g. real + Spinlocks. + +```console +ferris@box:~$ make raspboot + +[0] UART is live! +[1] Press a key to continue booting... Greetings fellow Rustacean! +[2] Switching MMU on now... MMU online. +[i] Memory layout: + 0x00000000 - 0x0007FFFF | 512 KiB | Kernel stack + 0x00080000 - 0x00082FFF | 12 KiB | Kernel code and RO data + 0x00083000 - 0x00085007 | 8 KiB | Kernel data and BSS + 0x3F000000 - 0x3FFFFFFF | 16 MiB | Device MMIO + +$> +``` diff --git a/0E_global_println/kernel8 b/0E_global_println/kernel8 new file mode 100755 index 0000000000000000000000000000000000000000..b759b2a1983c8a7b7e759fcd9640a761b5cad106 GIT binary patch literal 88168 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�r$WUQ0~v=U{8k2h22uA!F|p`ehwtgd`^aD>bGG8>r_=pQPzJpZ zzL;mhRt^p>CL{1|2P;mLrdLKi>A_;ug&!DvQ9*miP>S~#9Tsed&41DVz?4r6)AlPN zOF4Ylsi%mAJUd-^M@_{5*6*hl=U0d})Ne4~0ofo=y1x)>;Q55Efe*6vD`ay)wz9}V zCf~pdd361MZ~(Hg{tkaKT~W3mJpkF*+86w>-bfEXwt*KM7Vy<~XC8D#Mh2hHv+6t%taFO3Q*kByFVo%I zzdqfy{mQ4v$Vl8}Wt?Or1Ksr(I;=~JoYp1SN#FjHk?;Uy*dN6ETD%w3ScvoI`sq4&GC4=+y2?$?9frRcSh&Q(nsulFe$8Et zy(PpBtXoH_lsQ9(outmCL`E?0OHM9~jMNilsA3A*%#Vz?rzzVjc)cgVr{eSz$6QTK z!wTxdzBTO0S^EpBS-)i{A8kMRgYBc}TePSC4EEhSw!H^FkIIep0FygPb5SmL4|r$G zeFEiF?(4EB)_zB1gkrF7OxuW?)D>aO?lSBHVcggw;eB7P{~Y>0fwolsD&iQr&1K8) z!uV-Bf__e5K9}SEvO~dp)mv}Xko09dd(IaI=Y!`A=rM%fZye;MZ{XKIzs7p9C}KT} zdNfy~ZHPibhi*H(pYo#bFV~Qxm+`ykoZTC_Ru~+Ho~MG>Zs>lmKxKf$IfJ=$0(SBPWzzPo%FH3? zvTg`^x^G6rIFLVQ`m2gvf2&e7MAy?5%FOK*%A_M>WshM0pwv0H8EekEhTCea6VBO{ zVja^nkA${ub*vpgK5duH>OJY4*(+?PXD$iZ^ckR+0N>AA7gsN{EkI>kSI&{tGM?Lo!rmnTHA3lh6 zDXmA>nC`nL>BV>2^=aJ^`0*jsKZP~s!Yo-rLKZ#-H`NvG8~!7^Z}@O+5Mw*Fkc8KP z&t*Qou^70AGj(*o*8PR)Yb&t!6*8TMTuc_M>57+4(kF5Gs9dKZ*D0)hKS6qS{S-L8 z>YOv=fSobDW6gWgdCRChkW9w^FvVvAd%}L&4eg1z$J>*zvxtj?-g8Fq{ibKvZp;n3 zPxcygJ&_DSj{Vcv6POTtV0DRN54=t-viAgX;zH|XgC`;{pdttXgW9o&Ipn;lckf~6M*95#-?>T- zU|;k_?2En&|8@Z7v|S87jP5y}5xh|Ub=3a{?2S@>`ydzP*UI_PSVH^Vfqlo**mvBa zOs?Epy>#Ot*o50fUb++Upk0}9q+Tf=@_$dDo4>!1m#}r#lDGt-*ryw%|I?E%BIhpqto(!$VkiI;N@65mf-tI zRbJe5Y}=39ZPOF0=SU^TpBlgE+$C56W2lfzPM0;WF~8VaP3F4Xxt_Z|dKd1BaacoyV31Xzzy4 zaUo_6BW8`p3EtN)-p|y%%l!P*wKw#E;KzI*k3Tf8%jpAYy=)&iCN|sx9~g!_RnFO2 zvEh2I@Ns+~-7CB9+sE^uJ}}!B;Ojo^>IoW@~W;+_g%4bQ@U0dMEr1{ zn0I_7cs2IVI}ScOi^#!L(X@HTU+nIwEso4Pe%d)%b3Nxsm*aU-^}OT#&b@DW?A(^D zYx=zBKC`twwb|1W-Q3>Qc~=pkm!}MzaA8ftE{}cP>G3?_@!Z=~gWJ7ks?BWibaY1J z%|*+3{Q_S9e*O-Bz^(_f-s|{#2`}fjDxArvLatAW7JSA-;AArycq&}LY}_UIjw9m5 zmLBrs8Get5dZN9!3p%QdyFRQvL}J%O?eloKhu=ki<1vf3CrnSYE#awM?MXyCqebN7 z;h`#%NPp$Ktl8^^Kh^oA2y4g7rcFon39sZS9-d?rdpl>*~I9eOuS!mZsQZ+Kk>i zQgQao9zcke@O_Q-`Oe=`pj6Tlnqc^{`I;yk`vr=O;4=79S`fhUayCg^LAJ#uX&*r{mcBmjo)|jyJ#1WwzQZD zPeU!!^<8&$wQWj8H-PD4s!#LjKEE&E3;IGn!xvV4 zs;X+LuKLx08dO87p@ub|rfQm|Ykn=D1+|c7Xkp!_tGcG^x?d0IK|Q1!df4yttA5R| z`~CiaKj;tn4SzV`3#b7tpa=YcKp+?h1&lyA=nJYrEvN_m!9Xw=37-kyXZcC{rs?xObYX))WVNqb_p{d??+px7-BE#&&=jQaUIa(s4){`u>u zpP1;~!wZC;5becX&_8PXKZif*Xo0U@+}fUiOA&HTBwx1t|JCDVvT!BAL8Ln2XgY1} znb0YHVWMrTu=R#D0lU7--?2Z*u4l{b@(uhwg#?NEMKP~dZ|H1lZ_A!no`(C|+e|*M z{v6P^Gckbs0GA*8ckH^k(w1NN^}m2(X7Dn4`*R4FZ0+P$fz3@WPaBs(g+naIb2j~M z(6N6&;GWu3yl$==wX-~OE|Xn`v!%EkrS8}?@PXyh^ z>8`9i0{bwy97N=l1L%^n=2A*+53r;Geo)W3(*jV$?Bak|K_MEwUiUF5-n{t%~& zd|1%2Uxo{dt}OlyoZgs4H#vQO7X491S4jD2BxD5gTSQL>Hq8XRfhSh&D9)v?uS`Jy zE@S5y&ChJ^gb3XBXW=Pu`*{|96gQr)2tES0SF-5OvkD5?=CJ3FsQ-OFEK4Z+yQ$=X8-b*<1+u zC8vvgOVHosbdi4v`foU0I;APMppe%`&lzyUt*q$^@HGJI?l&#)nQBHk{IMSab zkBB2vKPfoaJ>LyJwC6Qhbez9s^j9YE+hRRKYtd^3tB*q@d>vs^30ckQ&t}oZd=%>( zQD4kQu^tk1F(1YHNYKT66zeEK7xPi9cLZI`N3s49^ar_|Vm&12k8rwJ9|?Lr=u}?< z2Qj~PbGjIpm|wr(bTO{qb4F!QE#)J|wUpC0ak?0n!Rf!`bRnnE=FJd*@)6?|^85v- zi}4EjUQQR|67=27-W){Ok3ByL*#W<+;Dd{>pNNo$(}n#A`prnfsJ{|=f0oy8;B;Xp zqTl17Q~tu<1pPnokjpP!oq%3~Bs*7q;RkkR*}0gHzDWW}TTo%2MiyPz;j>xvwH!CW zU*ys6bAK!Ni(ZxjH;Rwo-@x&iiG?4-jq?}v7fmp(=UF?%wJdp#LmtXU(8c~`%>;bJ zcwfrm(=b8(PSDW<`CnOhKF;Ys&7$`(x%B|1+l#XYu)0MpwxGspH4{Ca0gxqW_lD*GwB0g4L3pZh(U(S+e^91#u0iE_B*3SYTe9LBZ7hk6e`W{Xf>v2Kf z$LV5SF6e*9=?Am;;QJje2mYyXJZ?W^bcO85lK&OZbB*_x6VOjiK)*Bry{IrZ|64() za*FjjeWTX`P8aKTn~D=boZiFN&w}pbbg_OG^dP5u7LCW@)0}Q((Q7z;O%{DQqbp?j z&Exsp&*=>_$J6PDUd&+f#N6?8VYjEV@PCBY@AizZ-@xfRv*=0C72qbuEA|n-H4|vU zPYVA3jpxrTsGm!}PfkGp#sqY00y@rz)-Ld;enZrc*knRK1X8--kMF(qh5fSWpbP&m)_3)sF8sgH z*Uvaz#FyQi&8~l8qDtZMFH>YA9>dIPoR53cDiVp&hxt23JHJb7C zQY3y%F8she7Ps&nmD7d4ZQ$}d zFi)vGBHju5-JCAs<8ogAQBD{BSMo2^IU?KHbPi8s|wzey5rtfPZ?J2tm= zMq{`)c66rfC;LvC**9gw8+xoYskXNz?u@VR^7_bvgjcoys_a=~e|7fP&;AD3-yr?V z3RxK|VkN8~L`x0&CrlP}d)3^%O+>c)rwx4*G@PiVHbH%T0=jM0p);i#DKpwqpGdWD zsBdbk-_U}Omgr3n2Eu`0JQ_}zu~1SEGL$~7Q8MHY`plS`(83`ztVda+fUkbRs=5UW zYCpT6wX1VMm*!jWF#8+rU^gm=*NeS)ulM0pQ>VG$p1K99Zxem2$0y|!9lB{meM!w1 zk0#YvQVaaie8V{*bN*d}=fi2tw|0 z<`qh?a|0dz$C^@|A$(ZwXm2r9-xB*_^@a}rdb2YQE&($UFyi=(X+#r2e9!!tTsCwu zE{RY$6i8@(pBawF;{o;KbLoIAS`=Sd&7f)kDtus#e>^UMWJ^~^BLyZJFrh$v9@X$o z)&wv)om?uXGkIoA9J2og$p_o1wj=g2uV~m#l})~|{meY9#%8?+I-G(*r=K2VlcMf} z69MNLyx!`z&1@Q|Fo*ii%^S@6rUZr1=Qm8#AH{ssl7X;~Y2w2srRh)NN>yEMiy=o#rCu z5;>Hkv5|uo2Ca2NQ;V6Zk99S*;G9T@HyD33(H-mP8U_A_6;z7O4Qo)SZdid1;D!~# zBo*!0(4^PXb1vRM%xKw^*tChsr&60$)iLFo(P84?PdyHA(Flc+nJsF4GS%LS2Mx9w z3i)wXBaE{WYABjW+P-HTivW(*2RdGQeM0FU+_1q+EjPPwAikOm2mOgqG#pE4x?deT>4o?om;X5V17RbI zIIjlGXaWP##={d}5fe(%R8x(`Vt!vR7&c7bm})`$yq2olXL#!2QE;>eO`;~v1#}#v ziK?MkczpQb37V>HNHw)}*4u|J(J0{et9lYL>3TS(Che#!vbxZc)%UMm&C)nEiZFt+ zI!PSE!ReY1#I8qD4P#8;Db;@cfgQ6T(YE$BudX7MzyYFIC=k^llZt~p{&-wV#uGu! zh-qG*x25H=R4}$;rgLYuUFXfb^8qjF+E}dLs#R8L@AI!v-nz63+V~jkg;`CG?5m2LM z*hu>93`}Sx*cy$e+B<^vOqI}~YQR>)$#@XCRTybD6X1I7(ahZ6)Ye2DK#Vev;j~pe z<}>5GzUm7xutb*N<++pB+lW(g8(MJwtG){dXuRGvtML3F9>)&mgUx8p<@NHU%j>}|ITwy5ppcJ-gFZ11V;~s6JD_1Ec7%@RRuBw4( zh{h|j9rZ7$8GQ40i9*u_#7_6aVpMXyy z+V>yLe_V=$g)ib6HhwfLVxu~rT;urLf&C*Vs2xp@Ge0O&RC-d`fai*ZqPl71%JFPB zl&gcBIb>5-4|)jdPlWwg@5SOq&Mfs~_Ry8xLn0aX$AU=6LNR~X7?Y;ZL54ruo@$MD zVxfSHFPgwsQ>VE;6>WiWVq?cNvF8-flGq(k$7nCWPRnWInMuC}kIg2T&mS{GKGUD@!@K&zIPx9Gscj#QcKiJ%md+weQ++`LN63+) zVW%amVqZ|#J|YJ-U{9exg+=fNEIydxsfN97w-0|~Ys_ShKN*kfF-;4?vBAqE?SzFb zKdxto0oIb@1vCONUDc5JYDU~n%tqHL*L9>rMW`N%hT@5+7K>xAR0}4vs;j>0)cUSg zto|NSRbNMA`=)wk6I7*o99ecE>GNT_gmjbp8&$(WdF(7AbH{0U*hnaZw3wysc9PCF z*Z+hY{Zc}I`0U9q@g>6k@HVeZ(CxeUzAUKt4942yvjw}v`BzVw-9CWtI%6--*cUwG zI0pMt!$0?oeg}APk=@>v-2mq_#$Nb5f$voxygtXn9!gi0^3An?0Qy-xfj9&@$-d)|H+-#5ly+3o*7tF*6Z literal 0 HcmV?d00001 diff --git a/0E_global_println/kernel8.img b/0E_global_println/kernel8.img new file mode 100755 index 0000000000000000000000000000000000000000..773ab0f44434c5bf040beb24c2ec286ac808c1ee GIT binary patch literal 11093 zcmeHNe^gZWmH)o?`0-`{`Qf05Ci4(enK3HNFu#(f44|!$8XF)Sm@N_#70Y0Z9Ii1ccE(OlZA?%&j9)8HRD#)Yiiq!R zJd-0G@rsxgD`#~sl>P59d15gO5AEUPKrstXq5b0+cAztvIf#B@0}GoN+b150lMjsB zTq!Ez)PeKFC#u{b#$eIz@uF&5Y!w4GiWugW7Ffp})~*YGmQ zyp|oWOl6D8w;z#QOpm1IKpJ`2ZW5kE^T8?bU>e`zd}1IL&W$Yyfs&C-jDK$C&r z@KIhN48SjYiXC#s#m~x?BSx9zhmQ)%)KSa>hUsImN)WPVu*UHFF$%3e@Y^_rumryl z)j=>6ue8$olWEN)SJgLUg|@^f>e`pbD>KVQvS8n1zW0Q^5k{5j^B*tuT0R{lk0YUATdxTaK@dE6U@56NeR%F7J8s*dd} zW8O@eXPSS##|@CK{eQ`n;89MMA6Oo>jkwz;XZh10AG%#08?}2OAH|)OEC=i=-FflI zJUNg|Ix*V<%X#=A{45*o<$`ih(Buf*Kn`?Fwl+Roq$K7Ss(yPbTTpEzF7qn>512e8 zFnM@2uZ*}jtcxik*@-d7t;JY}z=&hsONN-U<6^w~lEF~*b_v?=7YLWc6!#^CeXUI73|28E+DE=J zoxEgPWZu3Kw(r8!Moy_`hsUp#^NNw{yfCp-P`(}0S!T{-eWJ9xY%h0qyg*`orR?l@ zZ~Wm_=Q5^T6FA?5zHdUb(ZZ#U%|Jqj#$=0a?XJ# z_2qom+h>eTvk{H;yLXQhpCEkQFPN=njMbrSUK@QI9%6mG(C%q6X5)mH$F9p*^vaQzit?+65h^r^l9m z4>~vl9r)o}gj?@_L+d9!ev@aIR|x*^_7bm|lQMXUdVsBq2aJ>xq zl>$@k=oVPtAwE5HiCxaccj9QYJyyYDwhM@5cW9X6Akmq zb5>^BGq@F>FzUI9;gB#IIFtKbidCG}(GSY_99J4mLNX#*|CI zbO<&l+mcU}z)oae5jHYASc}AUWlqKyseH)Zkv%a3H#R1#aeHECs(M~PZpT?6MUB0Y z4){Salj*!5o|`WR;g6Sjll=CxEUe}+K|tK+lp)Yu?+}z9@`&XEbC?h>&U{r=O#gYT zHPRs}u;-I>-tbTGICsP;gP@Oe;7pK=eUtJ=ndm1v343ku1NbRfPTWqp%pSl@@Y zB5xob}OjpPCu}X{)9~w8{Cl)S}Erl7fagFz#O6>m}uIr$f?hP}p0DDlA!7aFp#}l*p zpSyeP3mE(J+2e%^@0weHv7Vbz3_V)@eM8G%bNBtNWb-s*-f+PUt|bCJc440*H`)g6 z%<~X@u;7Lncv(dtKGPNy7TI!g;_Ma^vky@Y22Ie#Jc~h>vn!>%3+IAB!eW(fm}ozn zXtzEbr6<}UoLh!LAAFQ~ke4tgtz1l6a+^McIVv5_Jk~Xd_7&P(niImDU;*=xK9OV3 zi_oP7dM$-s&CuyOZtp>0mc`VlUMXhYiZ4`s6#0Aru`Wz`-;(21DEHHOAP47z;0mT# zbE9Vj^*n?#!LXfEV&H?b&jPxhKGCN4kWKogpI=yP)4%CGwejcJmmK+&Z(=8}(0*Bn z-{qo3@>EfV-1T|yJG8C<|Lucx{-qp8Ydbv@M`tP%eGfrTe#Fl~#3u5kSn5ymh6e>^ zrGDzG!~UgjotN%+)UWrMb686uVp<6CB2)7h$_Lj}Y@E8UXZx`a*eW$YCR~1sjf=ct z#CNMMvyQR+UXp?QLiI#l8MDmJ5oa}jr1RJi@`4|6e^4;^#$za7nXROwNHITAZR;yB<;_XV-v93`^?eI#`66fNzLM9SX~EehBqUj1zsY${ z+=@6Pj+f0b{MftjW19b=VCXLaE%bPP8ODl6GG*w@_JNvfMc?CO`(m5}i+S}NI0(N? zMNFjlpkcxp^gftwuDSRLn0y+h)1Ma8XYPS%L_b@@zYUt6ZlV6NLNAs7XlTjCS!6}% zYh@oD-B)(i{MTivSTAygFXa4LYvRzWWm_NfwZ5L%SvH!@{6VCEw8-wW)CoY1Pqp&wHH^M zNL-ui`> zDdvt~{8fyXVm`)q5Dv2UTF%g4G#Rxw`5bKS`weV6d#_WxfId|ltNMgZq0h0S&}W0C z`@+_DzJH-V<=A-A*N>0)|Lk|;A3gcI@!9%4{*C_{C;gsy@Wb(Y=+|d?rC-zUjf~MOQvvk`qOScWsZT$~b z-JT@fT2$TEw+Dp;RksDuE&Qnhb@4z5y4y_lhi><3x=lb$)qr_qGtzDSj{5djL4)xf z!KiLeKExS6rrY*8x}|;1GQW4B>cG#(rCt9#?)BdoSNHlJ=p3;*@BwNX#N$EKcERI< zLT3eI{u+xPGO1pNollBc56Y1Ur-a^)QHEU!mOzA8^tcrPpCD)l6PQAK9kIuUb~qS` zT(t~*R`wTT40aD5k5S+&Cxfe57_sf7WzZ~_R!ed)0knt%!Q&j}1A`gujIa{_qTx1ELeji>PYtiRW+)!f&umO+kk4Fuh&8P-Gsn)N+ zCIVZQce#o$a4d%E|C0e=Q{|oejBLqTCI^5`t$o2C^@bb(w!kr7!8uPoyZkTw_9VrH z|My!u-$i4>uVC-HV}dX+wb6k4r;R^;dRY;2w^13!dFCn68x9_gQ7R-a>YM~+xQ6rm zD$UUS%`~xl=1~?7*N93)VBrXC=a1)=>njB1I{a~RL!9DBW~WLLy$NW?WC$TX`b(MjQokP3`EH742vxce=*9?WYTSD$Y z-5M_7GDGJCRv~iUF!sG^Xt_6B$+(au8FR9|VM8j{ZPDmEQ6Jxn2XSFk;PyEZhTO-MAysWZ$7b0@;I@OZW>IA6hC#@rzhL&0~-=i2a;{ z_i3I(yWsNWA|_AaTN;mdW`k!s?C8Spw>&%bE&Tl1MapiYSNRU;=&VL_7{^>^m!9h- zUerEa#0IADn-ns9-dpj`Y1lahybi$jhxqxSbBNP)ex5{)F^Mti^I~mX;7LA0enB#F zH2zhLIT4$1ofJJ=P3(Le{#%Ngumm;XI%Vcjy7RhycXyKcAC~_PHH3t?g&OH3V^;Y) zv)i2y%YUo2BkyqoH<~%+QT}k*bS3UbasP7tnHZcMV|;s_X^B+ zb7!1#j$_WcGH+i!?g)*XcYh_vTH1xZnI)X5yN*k7z9g_y@5iyRYS?@P{xB>o^sNAP znzJ{K$?srZ;MPLd3$V=+?!h#iMaQ@}R`EidH~cL8S%HrS#0*#6ra}*Vr$tOZl!<$n z*3LxLhguHfP4R9EcoKiAU;1Y{_S5%ABoB9LS0HB;x$*p1rF-BZuRAX;Gc5%_Gtam5 zr1#)%jBh!S{*8m9*h_=(lef6U?hbB22)3*U!A|Sbz3vmSnQ3RZD18TK3{gF8;TCjT zxWxY1*uA(vFbj(tP;*vPEiF<8g$%1+$8;`XuC5NgJb?3bbZnt-NLb+0eW!CVb4B~p z(Qkr&Kd($~SgTxrW{omkS**-#DN=4U7b*gL0k)E>nE7%5XJ^W*B(v^m+#_w`Jol1) zIOCILA702lrsFE?5yY1kKWs1sUDiGA?L+MAGvDM|*1<;CDL!N~&o`m-VIk8u0~)GZ zO5&NkE>d`L2JzQ=v+$xi5A`T=c$nsPK{sKVi#qaipf}%))}=wzrBrJgEOB<+^Vq|b zyFo)WV?O8%ucVYKxDOAaE+smuF%6F;+7nhr>4`RsI35E1Flx-@bFjE{EZQ0jWGj-5 z_%T;DVz@1cwGA(4o{iu$rLAwa4h++g3c9Z~ypmRKLG7z!8UZd93u?NAwTbpb4Ikke z0j^=xz7Md@{Xd7E&Ip+y9)70U9X0Qeu;{iwut+5T8Pd;v{0aAIpXg7_aJN6{e&!XK z>zd%j-)}niAHd$Ad$M<7>-%AFYP#QxJAwP^9=f_tx`)1oS48gw?x`1|o2wVh8Nr<4 z)y$ItOc~INdA43~zM8#HNH3^=OtbfjzP2jF-#hDC7~+vvRJwccpg4NJJx2SB&aza$ zPQk{JVs2peJt*Bx(_N@q%cH)ayK4i^50smB!@mpg?!^0L;H2*?6RSX=KNUiKT|dto z_VK3fM%SJr$fxfk)|^FuKVncb?l42bJl~;n zLJR%<0DtE)oxr{5aomeuL3}%bahkUYF^ujUM|EDHe-HFO!rdtGI}BXJZ>z?SatX=p z!M)=M?j3u$B`eI#oHf0y_T@FxTRDDbO%q3ai8 zy`CogJz)$uQx>qa2=IJ>*k8aKLtc!p!d>hI$h{(@`Xaz3U@UDxrk%$9z)0igwQ6!?q zg5k*N9{e5V5NA^JEWN)5eJC%CxC=Ng&xdcy9dt(_fN%6W-B-Y|u>*Y1!PETSgJk0) zh>1w3r^s%U!zl*^U|Zb%AQndR&|c&r`li3t^zw%8x3JefLjC(X^3Y!)4~-(H{2IUa zkylF7UppAVyCJ>%;0Y}cy?~nR5N}ZPkOF^6fXx~}-=WbLaH5)r>X0k<^2UB@4*`n_ zXA{E3Vf`dK2wW0y&E79_?~>J=QXI`GG>7u&Yrr4Fz)!yUBj7&?{FFm! z4LWW;pZ;3I58VU5QN>UG{xI+q|F@QJ4_jS<2J>$EUTb5zI0Wn8J&YDKf zx}7I9S--pyskoxX`IPccjDg^%#y~Cq(7EoOF_7ry#=u#*VG&}W2Y3pEj5)dC&ROBp z#6Y?$yA#{*=0P!Vt}h_g-Hv@>tQ&Oze2DJ#c--rWIGY%J|8Og^P?Cxi4)so!ccuIT z)>%eAL}wDzxmQJ;snuGX!#d!X@4_!{x4+J&sqa15XZ=j{Y)Z945c$I}xa3kPc-8rr zTmqkcMs~8*n7ZWB@%GNL1n-hdBSMl*Ji^O4_)aWba>*|ox-3P{wrpelbJF_St<9}F zq{iwU&D+}^F*16jEO5eunnZo1=(AFic1hCX^+k9+UfbGK+bC^otFCDGSos-Vc(yp5HegkksdX^JBDeNqg(^?$%jN^X6Kqx@ogiwn5rl-BxX6pH_ceD8}e9 zYjW=9PdrurMdjtu6@6O%0gXRmn)*oVRhzG=eW|{tR$9NlWWyiFcU|_~e)WhH<$qY~ zkG2@o+q%AWJ?i6g^*^_*vHgSX|NG{zu4~>}ySloyzNW6NwsrNY*6rKcw!gT#t+~0e zrmniaY1`_i`Ym;BjXPGhyPcKJ{FU3A8k(A4Zd%z`-?Y7b<(8)Hs~hV#t)^-8-qu>9 zeybnosA+DkUENx{ZF^(es@82-6MPGBY5q_(=+R`Q-5o0>Q8kg#Q= zJq4;k&TI3QX!DF4bDxu*DlDsz>bFUa^)JgnLd~IW6^UG2hR#;tATip~DRHf1D zcsAOelgeMNZ>y=pB>2%&Qgf38MXAieao-&JCuYVR)Xy-$1V z^J=Oa8*4X9Rb{HJA9-YZ)61>ZFXmXPNDtLbQq|hl)+*_x>c;K0x$U{Rxp}#^TzhVQ zt|Ql(>&kWKdh&Af^73qX_PqQ&N1ij!mFLd$*m7-oHk-|E%eOgfPMgc-wt4Ki_B^}I zZnx*#9d@VPWp~>>`MLRd`L=v}ety0q-w4AS^-Y^=+f^rTejbjvy=n8dN66o$#@Z%w zX=zi`|D`A)dZIJWF4yd@G4g9|oblC1m#;N%$BFy3C2c^D6Z(Apt@r<-^Zyj_WLqO* z_3Ew7n-NlUocF^w7ytkDdQ~i%kq{tS+Yo5lqSmX0O{t+m>#{`chMGWqzOS`$KdC<7 z$%&4?sI^;hK%%&)@2d?jw$(Q`&D~d0)f3H4wc5V=Q>eaKg#o<>H2k=~Q=j?PD1JSz t{}~LEu8q;_PXX@vt!I_uT%+(2x5AhVazf`ajzHST6to literal 0 HcmV?d00001 diff --git a/0E_global_println/link.ld b/0E_global_println/link.ld new file mode 100644 index 00000000..cb6f21a6 --- /dev/null +++ b/0E_global_println/link.ld @@ -0,0 +1,57 @@ +/* + * MIT License + * + * Copyright (c) 2018 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +ENTRY(_boot_cores); + +SECTIONS +{ + . = 0x80000; /* This is already 4KiB aligned */ + __ro_start = .; + .text : + { + KEEP(*(.text.boot)) *(.text .text.*) + } + + .rodata : + { + *(.rodata .rodata.*) + } + . = ALIGN(4096); /* Fill up to 4KiB */ + __ro_end = .; + + .data : + { + *(.data .data.*) + } + + .bss ALIGN(8): + { + __bss_start = .; + *(.bss .bss.*) + *(COMMON) + __bss_end = .; + } + + /DISCARD/ : { *(.comment) *(.gnu*) *(.note*) *(.eh_frame*) } +} diff --git a/0E_global_println/raspi3_boot/Cargo.toml b/0E_global_println/raspi3_boot/Cargo.toml new file mode 100644 index 00000000..09732955 --- /dev/null +++ b/0E_global_println/raspi3_boot/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "raspi3_boot" +version = "0.1.0" +authors = ["Andre Richter "] +edition = "2018" + +[dependencies] +cortex-a = "2.3.1" +panic-abort = "0.3.1" +r0 = "0.2.2" diff --git a/0E_global_println/raspi3_boot/src/lib.rs b/0E_global_println/raspi3_boot/src/lib.rs new file mode 100644 index 00000000..bc9be005 --- /dev/null +++ b/0E_global_println/raspi3_boot/src/lib.rs @@ -0,0 +1,130 @@ +/* + * MIT License + * + * Copyright (c) 2018 Jorge Aparicio + * Copyright (c) 2018-2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#![deny(missing_docs)] +#![deny(warnings)] +#![no_std] + +//! Low-level boot of the Raspberry's processor + +extern crate panic_abort; + +/// Type check the user-supplied entry function. +#[macro_export] +macro_rules! entry { + ($path:path) => { + #[export_name = "main"] + pub unsafe fn __main() -> ! { + // type check the given path + let f: fn() -> ! = $path; + + f() + } + }; +} + +/// Reset function. +/// +/// Initializes the bss section before calling into the user's `main()`. +unsafe fn reset() -> ! { + extern "C" { + // Boundaries of the .bss section, provided by the linker script + static mut __bss_start: u64; + static mut __bss_end: u64; + } + + // Zeroes the .bss section + r0::zero_bss(&mut __bss_start, &mut __bss_end); + + extern "Rust" { + fn main() -> !; + } + + main() +} + +/// Prepare and execute transition from EL2 to EL1. +#[inline] +fn setup_and_enter_el1_from_el2() -> ! { + use cortex_a::{asm, regs::*}; + + const STACK_START: u64 = 0x80_000; + + // Enable timer counter registers for EL1 + CNTHCTL_EL2.write(CNTHCTL_EL2::EL1PCEN::SET + CNTHCTL_EL2::EL1PCTEN::SET); + + // No offset for reading the counters + CNTVOFF_EL2.set(0); + + // Set EL1 execution state to AArch64 + // TODO: Explain the SWIO bit + HCR_EL2.write(HCR_EL2::RW::EL1IsAarch64 + HCR_EL2::SWIO::SET); + + // Set up a simulated exception return. + // + // First, fake a saved program status, where all interrupts were + // masked and SP_EL1 was used as a stack pointer. + SPSR_EL2.write( + SPSR_EL2::D::Masked + + SPSR_EL2::A::Masked + + SPSR_EL2::I::Masked + + SPSR_EL2::F::Masked + + SPSR_EL2::M::EL1h, + ); + + // Second, let the link register point to reset(). + ELR_EL2.set(reset as *const () as u64); + + // Set up SP_EL1 (stack pointer), which will be used by EL1 once + // we "return" to it. + SP_EL1.set(STACK_START); + + // Use `eret` to "return" to EL1. This will result in execution of + // `reset()` in EL1. + asm::eret() +} + +/// Entrypoint of the processor. +/// +/// Parks all cores except core0 and checks if we started in EL2. If +/// so, proceeds with setting up EL1. +#[link_section = ".text.boot"] +#[no_mangle] +pub unsafe extern "C" fn _boot_cores() -> ! { + use cortex_a::{asm, regs::*}; + + const CORE_0: u64 = 0; + const CORE_MASK: u64 = 0x3; + const EL2: u32 = CurrentEL::EL::EL2.value; + + if (CORE_0 == MPIDR_EL1.get() & CORE_MASK) && (EL2 == CurrentEL.get()) { + setup_and_enter_el1_from_el2() + } + + // if not core0 or EL != 2, infinitely wait for events + loop { + asm::wfe(); + } +} diff --git a/0E_global_println/src/delays.rs b/0E_global_println/src/delays.rs new file mode 100644 index 00000000..b1c1fa0f --- /dev/null +++ b/0E_global_println/src/delays.rs @@ -0,0 +1,37 @@ +/* + * MIT License + * + * Copyright (c) 2018-2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use cortex_a::asm; + +/* + * + * Using the CPU's cycles + * + */ +/// Wait N CPU cycles (ARM CPU only) +pub fn wait_cycles(cyc: u32) { + for _ in 0..cyc { + asm::nop(); + } +} diff --git a/0E_global_println/src/devices.rs b/0E_global_println/src/devices.rs new file mode 100644 index 00000000..227b92c2 --- /dev/null +++ b/0E_global_println/src/devices.rs @@ -0,0 +1,26 @@ +/* + * MIT License + * + * Copyright (c) 2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +pub mod hw; +pub mod virt; diff --git a/0E_global_println/src/devices/hw.rs b/0E_global_println/src/devices/hw.rs new file mode 100644 index 00000000..877622ed --- /dev/null +++ b/0E_global_println/src/devices/hw.rs @@ -0,0 +1,31 @@ +/* + * MIT License + * + * Copyright (c) 2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +mod gpio; +mod pl011_uart; +mod videocore_mbox; + +pub use gpio::GPIO; +pub use pl011_uart::PL011Uart; +pub use videocore_mbox::VideocoreMbox; diff --git a/0E_global_println/src/devices/hw/gpio.rs b/0E_global_println/src/devices/hw/gpio.rs new file mode 100644 index 00000000..0d06dfa3 --- /dev/null +++ b/0E_global_println/src/devices/hw/gpio.rs @@ -0,0 +1,120 @@ +/* + * MIT License + * + * Copyright (c) 2018-2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use core::ops; +use register::{mmio::ReadWrite, register_bitfields}; + +// Descriptions taken from +// https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf +register_bitfields! { + u32, + + /// GPIO Function Select 1 + GPFSEL1 [ + /// Pin 15 + FSEL15 OFFSET(15) NUMBITS(3) [ + Input = 0b000, + Output = 0b001, + RXD0 = 0b100, // UART0 - Alternate function 0 + RXD1 = 0b010 // Mini UART - Alternate function 5 + + ], + + /// Pin 14 + FSEL14 OFFSET(12) NUMBITS(3) [ + Input = 0b000, + Output = 0b001, + TXD0 = 0b100, // UART0 - Alternate function 0 + TXD1 = 0b010 // Mini UART - Alternate function 5 + ] + ], + + /// GPIO Pull-up/down Clock Register 0 + GPPUDCLK0 [ + /// Pin 15 + PUDCLK15 OFFSET(15) NUMBITS(1) [ + NoEffect = 0, + AssertClock = 1 + ], + + /// Pin 14 + PUDCLK14 OFFSET(14) NUMBITS(1) [ + NoEffect = 0, + AssertClock = 1 + ] + ] +} + +#[allow(non_snake_case)] +#[repr(C)] +pub struct RegisterBlock { + pub GPFSEL0: ReadWrite, // 0x00 + pub GPFSEL1: ReadWrite, // 0x04 + pub GPFSEL2: ReadWrite, // 0x08 + pub GPFSEL3: ReadWrite, // 0x0C + pub GPFSEL4: ReadWrite, // 0x10 + pub GPFSEL5: ReadWrite, // 0x14 + __reserved_0: u32, // 0x18 + GPSET0: ReadWrite, // 0x1C + GPSET1: ReadWrite, // 0x20 + __reserved_1: u32, // + GPCLR0: ReadWrite, // 0x28 + __reserved_2: [u32; 2], // + GPLEV0: ReadWrite, // 0x34 + GPLEV1: ReadWrite, // 0x38 + __reserved_3: u32, // + GPEDS0: ReadWrite, // 0x40 + GPEDS1: ReadWrite, // 0x44 + __reserved_4: [u32; 7], // + GPHEN0: ReadWrite, // 0x64 + GPHEN1: ReadWrite, // 0x68 + __reserved_5: [u32; 10], // + pub GPPUD: ReadWrite, // 0x94 + pub GPPUDCLK0: ReadWrite, // 0x98 + pub GPPUDCLK1: ReadWrite, // 0x9C +} + +/// Public interface to the GPIO MMIO area +pub struct GPIO { + base_addr: u32, +} + +impl ops::Deref for GPIO { + type Target = RegisterBlock; + + fn deref(&self) -> &Self::Target { + unsafe { &*self.ptr() } + } +} + +impl GPIO { + pub fn new(base_addr: u32) -> GPIO { + GPIO { base_addr } + } + + /// Returns a pointer to the register block + fn ptr(&self) -> *const RegisterBlock { + self.base_addr as *const _ + } +} diff --git a/0E_global_println/src/devices/hw/pl011_uart.rs b/0E_global_println/src/devices/hw/pl011_uart.rs new file mode 100644 index 00000000..f98534e4 --- /dev/null +++ b/0E_global_println/src/devices/hw/pl011_uart.rs @@ -0,0 +1,276 @@ +/* + * MIT License + * + * Copyright (c) 2018-2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use super::gpio; +use super::videocore_mbox; +use crate::delays; +use crate::devices::virt::ConsoleOps; +use core::{ + ops, + sync::atomic::{compiler_fence, Ordering}, +}; +use cortex_a::asm; +use register::{mmio::*, register_bitfields}; + +// PL011 UART registers. +// +// Descriptions taken from +// https://github.com/raspberrypi/documentation/files/1888662/BCM2837-ARM-Peripherals.-.Revised.-.V2-1.pdf +register_bitfields! { + u32, + + /// Flag Register + FR [ + /// Transmit FIFO full. The meaning of this bit depends on the + /// state of the FEN bit in the UARTLCR_ LCRH Register. If the + /// FIFO is disabled, this bit is set when the transmit + /// holding register is full. If the FIFO is enabled, the TXFF + /// bit is set when the transmit FIFO is full. + TXFF OFFSET(5) NUMBITS(1) [], + + /// Receive FIFO empty. The meaning of this bit depends on the + /// state of the FEN bit in the UARTLCR_H Register. If the + /// FIFO is disabled, this bit is set when the receive holding + /// register is empty. If the FIFO is enabled, the RXFE bit is + /// set when the receive FIFO is empty. + RXFE OFFSET(4) NUMBITS(1) [] + ], + + /// Integer Baud rate divisor + IBRD [ + /// Integer Baud rate divisor + IBRD OFFSET(0) NUMBITS(16) [] + ], + + /// Fractional Baud rate divisor + FBRD [ + /// Fractional Baud rate divisor + FBRD OFFSET(0) NUMBITS(6) [] + ], + + /// Line Control register + LCRH [ + /// Word length. These bits indicate the number of data bits + /// transmitted or received in a frame. + WLEN OFFSET(5) NUMBITS(2) [ + FiveBit = 0b00, + SixBit = 0b01, + SevenBit = 0b10, + EightBit = 0b11 + ] + ], + + /// Control Register + CR [ + /// Receive enable. If this bit is set to 1, the receive + /// section of the UART is enabled. Data reception occurs for + /// UART signals. When the UART is disabled in the middle of + /// reception, it completes the current character before + /// stopping. + RXE OFFSET(9) NUMBITS(1) [ + Disabled = 0, + Enabled = 1 + ], + + /// Transmit enable. If this bit is set to 1, the transmit + /// section of the UART is enabled. Data transmission occurs + /// for UART signals. When the UART is disabled in the middle + /// of transmission, it completes the current character before + /// stopping. + TXE OFFSET(8) NUMBITS(1) [ + Disabled = 0, + Enabled = 1 + ], + + /// UART enable + UARTEN OFFSET(0) NUMBITS(1) [ + /// If the UART is disabled in the middle of transmission + /// or reception, it completes the current character + /// before stopping. + Disabled = 0, + Enabled = 1 + ] + ], + + /// Interupt Clear Register + ICR [ + /// Meta field for all pending interrupts + ALL OFFSET(0) NUMBITS(11) [] + ] +} + +#[allow(non_snake_case)] +#[repr(C)] +pub struct RegisterBlock { + DR: ReadWrite, // 0x00 + __reserved_0: [u32; 5], // 0x04 + FR: ReadOnly, // 0x18 + __reserved_1: [u32; 2], // 0x1c + IBRD: WriteOnly, // 0x24 + FBRD: WriteOnly, // 0x28 + LCRH: WriteOnly, // 0x2C + CR: WriteOnly, // 0x30 + __reserved_2: [u32; 4], // 0x34 + ICR: WriteOnly, // 0x44 +} + +pub enum PL011UartError { + MailboxError, +} +pub type Result = ::core::result::Result; + +pub struct PL011Uart { + base_addr: u32, +} + +impl ops::Deref for PL011Uart { + type Target = RegisterBlock; + + fn deref(&self) -> &Self::Target { + unsafe { &*self.ptr() } + } +} + +impl PL011Uart { + pub fn new(base_addr: u32) -> PL011Uart { + PL011Uart { base_addr } + } + + /// Returns a pointer to the register block + fn ptr(&self) -> *const RegisterBlock { + self.base_addr as *const _ + } + + ///Set baud rate and characteristics (115200 8N1) and map to GPIO + pub fn init( + &self, + v_mbox: &mut videocore_mbox::VideocoreMbox, + gpio: &gpio::GPIO, + ) -> Result<()> { + // turn off UART0 + self.CR.set(0); + + // set up clock for consistent divisor values + v_mbox.buffer[0] = 9 * 4; + v_mbox.buffer[1] = videocore_mbox::REQUEST; + v_mbox.buffer[2] = videocore_mbox::tag::SETCLKRATE; + v_mbox.buffer[3] = 12; + v_mbox.buffer[4] = 8; + v_mbox.buffer[5] = videocore_mbox::clock::UART; // UART clock + v_mbox.buffer[6] = 4_000_000; // 4Mhz + v_mbox.buffer[7] = 0; // skip turbo setting + v_mbox.buffer[8] = videocore_mbox::tag::LAST; + + // Insert a compiler fence that ensures that all stores to the + // mbox buffer are finished before the GPU is signaled (which + // is done by a store operation as well). + compiler_fence(Ordering::Release); + + if v_mbox.call(videocore_mbox::channel::PROP).is_err() { + return Err(PL011UartError::MailboxError); // Abort if UART clocks couldn't be set + }; + + // map UART0 to GPIO pins + gpio.GPFSEL1 + .modify(gpio::GPFSEL1::FSEL14::TXD0 + gpio::GPFSEL1::FSEL15::RXD0); + + gpio.GPPUD.set(0); // enable pins 14 and 15 + delays::wait_cycles(150); + + gpio.GPPUDCLK0.modify( + gpio::GPPUDCLK0::PUDCLK14::AssertClock + gpio::GPPUDCLK0::PUDCLK15::AssertClock, + ); + delays::wait_cycles(150); + + gpio.GPPUDCLK0.set(0); + + self.ICR.write(ICR::ALL::CLEAR); + self.IBRD.write(IBRD::IBRD.val(2)); // Results in 115200 baud + self.FBRD.write(FBRD::FBRD.val(0xB)); + self.LCRH.write(LCRH::WLEN::EightBit); // 8N1 + + self.CR + .write(CR::UARTEN::Enabled + CR::TXE::Enabled + CR::RXE::Enabled); + + Ok(()) + } +} + +impl Drop for PL011Uart { + fn drop(&mut self) { + self.CR + .write(CR::UARTEN::Disabled + CR::TXE::Disabled + CR::RXE::Disabled); + } +} + +impl ConsoleOps for PL011Uart { + /// Send a character + fn putc(&self, c: char) { + // wait until we can send + loop { + if !self.FR.is_set(FR::TXFF) { + break; + } + + asm::nop(); + } + + // write the character to the buffer + self.DR.set(c as u32); + } + + /// Display a string + fn puts(&self, string: &str) { + for c in string.chars() { + // convert newline to carrige return + newline + if c == '\n' { + self.putc('\r') + } + + self.putc(c); + } + } + + /// Receive a character + fn getc(&self) -> char { + // wait until something is in the buffer + loop { + if !self.FR.is_set(FR::RXFE) { + break; + } + + asm::nop(); + } + + // read it and return + let mut ret = self.DR.get() as u8 as char; + + // convert carrige return to newline + if ret == '\r' { + ret = '\n' + } + + ret + } +} diff --git a/0E_global_println/src/devices/hw/videocore_mbox.rs b/0E_global_println/src/devices/hw/videocore_mbox.rs new file mode 100644 index 00000000..1409f54a --- /dev/null +++ b/0E_global_println/src/devices/hw/videocore_mbox.rs @@ -0,0 +1,164 @@ +/* + * MIT License + * + * Copyright (c) 2018-2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use core::ops; +use cortex_a::asm; +use register::{ + mmio::{ReadOnly, WriteOnly}, + register_bitfields, +}; + +register_bitfields! { + u32, + + STATUS [ + FULL OFFSET(31) NUMBITS(1) [], + EMPTY OFFSET(30) NUMBITS(1) [] + ] +} + +#[allow(non_snake_case)] +#[repr(C)] +pub struct RegisterBlock { + READ: ReadOnly, // 0x00 + __reserved_0: [u32; 5], // 0x04 + STATUS: ReadOnly, // 0x18 + __reserved_1: u32, // 0x1C + WRITE: WriteOnly, // 0x20 +} + +// Custom errors +pub enum VideocoreMboxError { + ResponseError, + UnknownError, +} +pub type Result = ::core::result::Result; + +// Channels +pub mod channel { + pub const PROP: u32 = 8; +} + +// Tags +pub mod tag { + pub const SETCLKRATE: u32 = 0x38002; + pub const LAST: u32 = 0; +} + +// Clocks +pub mod clock { + pub const UART: u32 = 0x0_0000_0002; +} + +// Responses +mod response { + pub const SUCCESS: u32 = 0x8000_0000; + pub const ERROR: u32 = 0x8000_0001; // error parsing request buffer (partial response) +} + +pub const REQUEST: u32 = 0; + +// Public interface to the mailbox +#[repr(C)] +#[repr(align(16))] +pub struct VideocoreMbox { + // The address for buffer needs to be 16-byte aligned so that the Videcore + // can handle it properly. Hence, put it at the start of the struct so that + // the align attribute is effective. + pub buffer: [u32; 36], + base_addr: u32, +} + +/// Deref to RegisterBlock +/// +/// Allows writing +/// ``` +/// self.STATUS.read() +/// ``` +/// instead of something along the lines of +/// ``` +/// unsafe { (*Mbox::ptr()).STATUS.read() } +/// ``` +impl ops::Deref for VideocoreMbox { + type Target = RegisterBlock; + + fn deref(&self) -> &Self::Target { + unsafe { &*self.ptr() } + } +} + +impl VideocoreMbox { + pub fn new(base_addr: u32) -> VideocoreMbox { + VideocoreMbox { + buffer: [0; 36], + base_addr, + } + } + + /// Returns a pointer to the register block + fn ptr(&self) -> *const RegisterBlock { + self.base_addr as *const _ + } + + /// Make a mailbox call. Returns Err(MboxError) on failure, Ok(()) success + pub fn call(&self, channel: u32) -> Result<()> { + // wait until we can write to the mailbox + loop { + if !self.STATUS.is_set(STATUS::FULL) { + break; + } + + asm::nop(); + } + + let buf_ptr = self.buffer.as_ptr() as u32; + + // write the address of our message to the mailbox with channel identifier + self.WRITE.set((buf_ptr & !0xF) | (channel & 0xF)); + + // now wait for the response + loop { + // is there a response? + loop { + if !self.STATUS.is_set(STATUS::EMPTY) { + break; + } + + asm::nop(); + } + + let resp: u32 = self.READ.get(); + + // is it a response to our message? + if ((resp & 0xF) == channel) && ((resp & !0xF) == buf_ptr) { + // is it a valid successful response? + return match self.buffer[1] { + response::SUCCESS => Ok(()), + response::ERROR => Err(VideocoreMboxError::ResponseError), + _ => Err(VideocoreMboxError::UnknownError), + }; + } + } + } +} diff --git a/0E_global_println/src/devices/virt.rs b/0E_global_println/src/devices/virt.rs new file mode 100644 index 00000000..30ed5469 --- /dev/null +++ b/0E_global_println/src/devices/virt.rs @@ -0,0 +1,27 @@ +/* + * MIT License + * + * Copyright (c) 2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +mod console; + +pub use console::{Console, ConsoleOps}; diff --git a/0E_global_println/src/devices/virt/console.rs b/0E_global_println/src/devices/virt/console.rs new file mode 100644 index 00000000..088971c6 --- /dev/null +++ b/0E_global_println/src/devices/virt/console.rs @@ -0,0 +1,136 @@ +/* + * MIT License + * + * Copyright (c) 2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use crate::devices::hw; +use core::fmt; + +/// A trait that must be implemented by devices that are candidates for the +/// global console. +#[allow(unused_variables)] +pub trait ConsoleOps: Drop { + fn putc(&self, c: char) {} + fn puts(&self, string: &str) {} + fn getc(&self) -> char { + ' ' + } + fn flush(&self) {} +} + +/// A dummy console that just ignores its inputs. +pub struct NullConsole; +impl Drop for NullConsole { + fn drop(&mut self) {} +} +impl ConsoleOps for NullConsole {} + +/// Possible outputs which the console can store. +pub enum Output { + None(NullConsole), + PL011Uart(hw::PL011Uart), +} + +impl From for Output { + fn from(instance: hw::PL011Uart) -> Self { + Output::PL011Uart(instance) + } +} + +pub struct Console { + output: Output, +} + +impl Console { + pub const fn new() -> Console { + Console { + output: Output::None(NullConsole {}), + } + } + + #[inline(always)] + fn current_ptr(&self) -> &dyn ConsoleOps { + match &self.output { + Output::None(i) => i, + Output::PL011Uart(i) => i, + } + } + + /// Overwrite the current output. The old output will go out of scope and + /// it's Drop function will be called. + pub fn replace_with(&mut self, x: Output) { + self.current_ptr().flush(); + + self.output = x; + } + + /// A command prompt. Currently does nothing. + pub fn command_prompt(&self) -> ! { + self.puts("\n$> "); + + let mut input; + loop { + input = self.getc(); + + if input == '\n' { + self.puts("\n$> ") + } else { + self.putc(input); + } + } + } +} + +impl Drop for Console { + fn drop(&mut self) {} +} + +/// Dispatch the respective function to the currently stored output device. +impl ConsoleOps for Console { + fn putc(&self, c: char) { + self.current_ptr().putc(c); + } + + fn puts(&self, string: &str) { + self.current_ptr().puts(string); + } + + fn getc(&self) -> char { + self.current_ptr().getc() + } + + fn flush(&self) { + self.current_ptr().flush() + } +} + +/// Implementing this trait enables usage of the format_args! macros, which in +/// turn are used to implement the kernel's print! and println! macros. +/// +/// See src/macros.rs. +impl fmt::Write for Console { + fn write_str(&mut self, s: &str) -> fmt::Result { + self.current_ptr().puts(s); + + Ok(()) + } +} diff --git a/0E_global_println/src/macros.rs b/0E_global_println/src/macros.rs new file mode 100644 index 00000000..28280be9 --- /dev/null +++ b/0E_global_println/src/macros.rs @@ -0,0 +1,49 @@ +/* + * MIT License + * + * Copyright (c) 2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use core::fmt; + +// https://doc.rust-lang.org/src/std/macros.rs.html +#[macro_export] +macro_rules! print { + ($($arg:tt)*) => ($crate::macros::_print(format_args!($($arg)*))); +} + +// https://doc.rust-lang.org/src/std/macros.rs.html +#[macro_export] +macro_rules! println { + () => (print!("\n")); + ($($arg:tt)*) => ({ + $crate::macros::_print(format_args_nl!($($arg)*)); + }) +} + +#[doc(hidden)] +pub fn _print(args: fmt::Arguments) { + use core::fmt::Write; + + crate::CONSOLE.lock(|c| { + c.write_fmt(args).unwrap(); + }) +} diff --git a/0E_global_println/src/main.rs b/0E_global_println/src/main.rs new file mode 100644 index 00000000..bd9fb8e3 --- /dev/null +++ b/0E_global_println/src/main.rs @@ -0,0 +1,106 @@ +/* + * MIT License + * + * Copyright (c) 2018-2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#![no_std] +#![no_main] +#![feature(const_fn)] +#![feature(custom_attribute)] +#![feature(format_args_nl)] +#![feature(range_contains)] + +mod delays; +mod devices; +mod macros; +mod memory; +mod sync; + +/// The global console. Output of the print! and println! macros. +static CONSOLE: sync::NullLock = + sync::NullLock::new(devices::virt::Console::new()); + +fn kernel_entry() -> ! { + use devices::hw; + use devices::virt::ConsoleOps; + + // This will be invisible, because CONSOLE is dispatching to the NullConsole + // at this point in time. + println!("Is there anybody out there?"); + + //------------------------------------------------------------ + // Instantiate GPIO device + //------------------------------------------------------------ + let gpio = hw::GPIO::new(memory::map::GPIO_BASE); + + //------------------------------------------------------------ + // Instantiate Videocore Mailbox + //------------------------------------------------------------ + let mut v_mbox = hw::VideocoreMbox::new(memory::map::VIDEOCORE_MBOX_BASE); + + //------------------------------------------------------------ + // Instantiate PL011 UART and put it in CONSOLE + //------------------------------------------------------------ + let uart = hw::PL011Uart::new(memory::map::PL011_UART_BASE); + + match uart.init(&mut v_mbox, &gpio) { + Ok(_) => { + CONSOLE.lock(|c| { + // Moves uart into the global CONSOLE. It is not accessible + // anymore for the remaining parts of kernel_entry(). + c.replace_with(uart.into()); + }); + + println!("\n[0] UART is live!"); + } + Err(_) => loop { + cortex_a::asm::wfe() // If UART fails, abort early + }, + } + + //------------------------------------------------------------ + // Greet the user + //------------------------------------------------------------ + print!("[1] Press a key to continue booting... "); + CONSOLE.lock(|c| { + c.getc(); + }); + println!("Greetings fellow Rustacean!"); + + //------------------------------------------------------------ + // Bring up memory subsystem + //------------------------------------------------------------ + print!("[2] Switching MMU on now... "); + unsafe { memory::mmu::init() }; + println!("MMU online."); + + memory::print_layout(); + + //------------------------------------------------------------ + // Start a command prompt + //------------------------------------------------------------ + CONSOLE.lock(|c| { + c.command_prompt(); + }) +} + +raspi3_boot::entry!(kernel_entry); diff --git a/0E_global_println/src/memory.rs b/0E_global_println/src/memory.rs new file mode 100644 index 00000000..ee828c9d --- /dev/null +++ b/0E_global_println/src/memory.rs @@ -0,0 +1,113 @@ +/* + * MIT License + * + * Copyright (c) 2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use crate::println; + +pub mod mmu; + +/// The system memory map. +#[rustfmt::skip] +pub mod map { + pub const KERN_STACK_BOT: u32 = 0x0000_0000; + pub const KERN_STACK_TOP: u32 = 0x0007_FFFF; + + pub const MMIO_BASE: u32 = 0x3F00_0000; + pub const VIDEOCORE_MBOX_BASE: u32 = MMIO_BASE + 0x0000_B880; + pub const GPIO_BASE: u32 = MMIO_BASE + 0x0020_0000; + pub const PL011_UART_BASE: u32 = MMIO_BASE + 0x0020_1000; + + pub const PHYS_ADDR_MAX: u32 = 0x3FFF_FFFF; +} + +const PAGESIZE: u64 = 4096; + +fn get_ro_start_end() -> (u64, u64) { + // Using the linker script, we ensure that the RO area is consecutive and 4 + // KiB aligned, and we export the boundaries via symbols. + extern "C" { + // The inclusive start of the read-only area, aka the address of the + // first byte of the area. + static __ro_start: u64; + + // The non-inclusive end of the read-only area, aka the address of the + // first byte _after_ the RO area. + static __ro_end: u64; + } + + unsafe { + // Notice the subtraction to calculate the last page index of the RO + // area and not the first page index after the RO area. + ( + &__ro_start as *const _ as u64, + &__ro_end as *const _ as u64 - 1, + ) + } +} + +pub fn print_layout() { + use crate::memory::map::*; + + // log2(1024) + const KIB_RSHIFT: u32 = 10; + + // log2(1024 * 1024) + const MIB_RSHIFT: u32 = 20; + + println!("[i] Memory layout:"); + + println!( + " {:#010X} - {:#010X} | {: >4} KiB | Kernel stack", + KERN_STACK_BOT, + KERN_STACK_TOP, + (KERN_STACK_TOP - KERN_STACK_BOT + 1) >> KIB_RSHIFT + ); + + let (ro_start, ro_end) = get_ro_start_end(); + println!( + " {:#010X} - {:#010X} | {: >4} KiB | Kernel code and RO data", + ro_start, + ro_end, + (ro_end - ro_start + 1) >> KIB_RSHIFT + ); + + extern "C" { + static __bss_end: u64; + } + + let start = ro_end + 1; + let end = unsafe { &__bss_end as *const _ as u64 } - 1; + println!( + " {:#010X} - {:#010X} | {: >4} KiB | Kernel data and BSS", + start, + end, + (end - start + 1) >> KIB_RSHIFT + ); + + println!( + " {:#010X} - {:#010X} | {: >4} MiB | Device MMIO", + MMIO_BASE, + PHYS_ADDR_MAX, + (PHYS_ADDR_MAX - MMIO_BASE + 1) >> MIB_RSHIFT + ); +} diff --git a/0E_global_println/src/memory/mmu.rs b/0E_global_println/src/memory/mmu.rs new file mode 100644 index 00000000..4c92a0aa --- /dev/null +++ b/0E_global_println/src/memory/mmu.rs @@ -0,0 +1,229 @@ +/* + * MIT License + * + * Copyright (c) 2018-2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use cortex_a::{barrier, regs::*}; +use register::register_bitfields; + +register_bitfields! {u64, + // AArch64 Reference Manual page 2150 + STAGE1_DESCRIPTOR [ + /// Execute-never + XN OFFSET(54) NUMBITS(1) [ + False = 0, + True = 1 + ], + + /// Various address fields, depending on use case + LVL2_OUTPUT_ADDR_4KiB OFFSET(21) NUMBITS(27) [], // [47:21] + NEXT_LVL_TABLE_ADDR_4KiB OFFSET(12) NUMBITS(36) [], // [47:12] + + /// Access flag + AF OFFSET(10) NUMBITS(1) [ + False = 0, + True = 1 + ], + + /// Shareability field + SH OFFSET(8) NUMBITS(2) [ + OuterShareable = 0b10, + InnerShareable = 0b11 + ], + + /// Access Permissions + AP OFFSET(6) NUMBITS(2) [ + RW_EL1 = 0b00, + RW_EL1_EL0 = 0b01, + RO_EL1 = 0b10, + RO_EL1_EL0 = 0b11 + ], + + /// Memory attributes index into the MAIR_EL1 register + AttrIndx OFFSET(2) NUMBITS(3) [], + + TYPE OFFSET(1) NUMBITS(1) [ + Block = 0, + Table = 1 + ], + + VALID OFFSET(0) NUMBITS(1) [ + False = 0, + True = 1 + ] + ] +} + +trait BaseAddr { + fn base_addr(&self) -> u64; +} + +impl BaseAddr for [u64; 512] { + fn base_addr(&self) -> u64 { + self as *const u64 as u64 + } +} + +const NUM_ENTRIES_4KIB: usize = 512; + +// We need a wrapper struct here so that we can make use of the align attribute. +#[repr(C)] +#[repr(align(4096))] +struct PageTable { + entries: [u64; NUM_ENTRIES_4KIB], +} + +static mut LVL2_TABLE: PageTable = PageTable { + entries: [0; NUM_ENTRIES_4KIB], +}; +static mut SINGLE_LVL3_TABLE: PageTable = PageTable { + entries: [0; NUM_ENTRIES_4KIB], +}; + +/// Set up identity mapped page tables for the first 1 GiB of address space. +pub unsafe fn init() { + // First, define the three memory types that we will map. Cacheable and + // non-cacheable normal DRAM, and device. + MAIR_EL1.write( + // Attribute 2 + MAIR_EL1::Attr2_HIGH::Memory_OuterNonCacheable + + MAIR_EL1::Attr2_LOW_MEMORY::InnerNonCacheable + + // Attribute 1 + + MAIR_EL1::Attr1_HIGH::Memory_OuterWriteBack_NonTransient_ReadAlloc_WriteAlloc + + MAIR_EL1::Attr1_LOW_MEMORY::InnerWriteBack_NonTransient_ReadAlloc_WriteAlloc + + // Attribute 0 + + MAIR_EL1::Attr0_HIGH::Device + + MAIR_EL1::Attr0_LOW_DEVICE::Device_nGnRE, + ); + + // Descriptive consts for indexing into the correct MAIR_EL1 attributes. + #[allow(dead_code)] + mod mair { + pub const DEVICE: u64 = 0; + pub const NORMAL: u64 = 1; + pub const NORMAL_NON_CACHEABLE: u64 = 2; + } + + // The first 2 MiB. + // + // Set up the first LVL2 entry, pointing to the base address of a follow-up + // table containing 4 KiB pages. + // + // 0x0000_0000_0000_0000 | + // |> 2 MiB + // 0x0000_0000_001F_FFFF | + let lvl3_base: u64 = SINGLE_LVL3_TABLE.entries.base_addr() >> 12; + LVL2_TABLE.entries[0] = (STAGE1_DESCRIPTOR::VALID::True + + STAGE1_DESCRIPTOR::TYPE::Table + + STAGE1_DESCRIPTOR::NEXT_LVL_TABLE_ADDR_4KiB.val(lvl3_base)) + .value; + + // Fill the rest of the LVL2 (2 MiB) entries as block descriptors. + // + // Differentiate between + // - cacheable DRAM + // - device memory + // + // Ranges are stored in memory.rs. + // + // 0x0000_0000_0020_0000 | + // |> 1006 MiB cacheable DRAM + // 0x0000_0000_3EFF_FFFF | + // 0x0000_0000_3F00_0000 | + // |> 16 MiB device (MMIO) + // 0x0000_0000_4000_0000 | + let mmio_first_block_index: u64 = (crate::memory::map::MMIO_BASE >> 21).into(); + + let common = STAGE1_DESCRIPTOR::VALID::True + + STAGE1_DESCRIPTOR::TYPE::Block + + STAGE1_DESCRIPTOR::AP::RW_EL1 + + STAGE1_DESCRIPTOR::AF::True + + STAGE1_DESCRIPTOR::XN::True; + + // Notice the skip(1) which makes the iteration start at the second 2 MiB + // block (0x20_0000). + for (i, entry) in LVL2_TABLE.entries.iter_mut().enumerate().skip(1) { + let j: u64 = i as u64; + + let mem_attr = if j >= mmio_first_block_index { + STAGE1_DESCRIPTOR::SH::OuterShareable + STAGE1_DESCRIPTOR::AttrIndx.val(mair::DEVICE) + } else { + STAGE1_DESCRIPTOR::SH::InnerShareable + STAGE1_DESCRIPTOR::AttrIndx.val(mair::NORMAL) + }; + + *entry = (common + mem_attr + STAGE1_DESCRIPTOR::LVL2_OUTPUT_ADDR_4KiB.val(j)).value; + } + + // Finally, fill the single LVL3 table (4 KiB granule). Differentiate + // between code+RO and RW pages. + let (ro_start_addr, ro_end_addr) = super::get_ro_start_end(); + + let ro_first_page_index = ro_start_addr / super::PAGESIZE; + let ro_last_page_index = ro_end_addr / super::PAGESIZE; + + let common = STAGE1_DESCRIPTOR::VALID::True + + STAGE1_DESCRIPTOR::TYPE::Table + + STAGE1_DESCRIPTOR::AttrIndx.val(mair::NORMAL) + + STAGE1_DESCRIPTOR::SH::InnerShareable + + STAGE1_DESCRIPTOR::AF::True; + + for (i, entry) in SINGLE_LVL3_TABLE.entries.iter_mut().enumerate() { + let j: u64 = i as u64; + + let mem_attr = if (ro_first_page_index..=ro_last_page_index).contains(&j) { + STAGE1_DESCRIPTOR::AP::RO_EL1 + STAGE1_DESCRIPTOR::XN::False + } else { + STAGE1_DESCRIPTOR::AP::RW_EL1 + STAGE1_DESCRIPTOR::XN::True + }; + + *entry = (common + mem_attr + STAGE1_DESCRIPTOR::NEXT_LVL_TABLE_ADDR_4KiB.val(j)).value; + } + + // Point to the LVL2 table base address in TTBR0. + TTBR0_EL1.set_baddr(LVL2_TABLE.entries.base_addr()); + + // Configure various settings of stage 1 of the EL1 translation regime. + let ips = ID_AA64MMFR0_EL1.read(ID_AA64MMFR0_EL1::PARange); + TCR_EL1.write( + TCR_EL1::TBI0::Ignored + + TCR_EL1::IPS.val(ips) + + TCR_EL1::TG0::KiB_4 // 4 KiB granule + + TCR_EL1::SH0::Inner + + TCR_EL1::ORGN0::WriteBack_ReadAlloc_WriteAlloc_Cacheable + + TCR_EL1::IRGN0::WriteBack_ReadAlloc_WriteAlloc_Cacheable + + TCR_EL1::EPD0::EnableTTBR0Walks + + TCR_EL1::T0SZ.val(34), // Start walks at level 2 + ); + + // Switch the MMU on. + // + // First, force all previous changes to be seen before the MMU is enabled. + barrier::isb(barrier::SY); + + // Enable the MMU and turn on data and instruction caching. + SCTLR_EL1.modify(SCTLR_EL1::M::Enable + SCTLR_EL1::C::Cacheable + SCTLR_EL1::I::Cacheable); + + // Force MMU init to complete before next instruction + barrier::isb(barrier::SY); +} diff --git a/0E_global_println/src/sync.rs b/0E_global_println/src/sync.rs new file mode 100644 index 00000000..55a45e31 --- /dev/null +++ b/0E_global_println/src/sync.rs @@ -0,0 +1,62 @@ +/* + * MIT License + * + * Copyright (c) 2019 Andre Richter + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +use core::cell::UnsafeCell; + +pub struct NullLock { + data: UnsafeCell, +} + +// Since we are instantiating this struct as a static variable, which could +// potentially be shared between different threads, we need to tell the compiler +// that sharing of this struct is safe by marking it with the Sync trait. +// +// At this point in time, we can do so without worrying, because the kernel +// anyways runs on a single core and interrupts are disabled. In short, multiple +// threads don't exist yet in our code. +// +// Literature: +// https://doc.rust-lang.org/beta/nomicon/send-and-sync.html +// https://doc.rust-lang.org/book/ch16-04-extensible-concurrency-sync-and-send.html +unsafe impl Sync for NullLock {} + +impl NullLock { + pub const fn new(data: T) -> NullLock { + NullLock { + data: UnsafeCell::new(data), + } + } +} + +impl NullLock { + pub fn lock(&self, f: F) -> R + where + F: FnOnce(&mut T) -> R, + { + // In a real lock, there would be code around this line that ensures + // that this mutable reference will ever only be given out to one thread + // at a time. + f(unsafe { &mut *self.data.get() }) + } +}