Cleaner startup process.
Cleaner cross-platform portability (platform.h).
Removed ARMv5.
Removed ARMv7-m
Removed XScale
Changed kernel device paging interface and fixed bugs.
Signed-off-by: Timothy Roscoe <troscoe@inf.ethz.ch>
"x2apic",
"amd64",
"pl130_gic",
+ "pl011_uart",
"sp804_pit",
"cortex_a9_pit",
"cortex_a9_gt",
- "a9scu",
+ "cortex_a9_scu",
"ti_i2c",
"ti_twl6030",
"sdhc",
"omap/omap44xx_cam_prm",
"omap/omap44xx_ckgen_cm2",
"omap/omap44xx_ckgen_prm",
+ "omap/omap44xx_cortexa9_wugen",
"omap/omap44xx_cortex_m3_nvic",
"omap/omap44xx_ctrlmod",
"omap/omap44xx_device_prm",
"pc16550d_mem",
"pci_hdr0",
"pci_hdr0_mem",
- "pci_hdr1",
- "pl011_uart"
+ "pci_hdr1"
], arch <- allArchitectures
]
* This implements private timers and watchdogs
*/
- device cortex_a9_gt msbfirst ( addr base ) "Cortex A9 Global Timer" {
-
- register TimerCounterLow addr(base, 0x0) "Global Timer Counter Register (Lower Word)" type(uint32);
- register TimerCounterHigh addr(base, 0x4) "Global Timer Counter Register (Upper Word)" type(uint32);
-
- register TimerControl addr(base, 0x8) "Global Timer Control Register" {
- _ 16 rsvd;
- prescale 8 rw "Prescale factor";
- _ 4 rsvd;
- auto_increment 1 rw "Single shot or increment mode";
- int_enable 1 rw "Interrupt enable bit";
- comp_enable 1 rw "Enable comparision between counter and comparator register";
- timer_enable 1 rw "Timer enable bit";
- };
-
- register TimerIntStat addr(base, 0xc) "Global Timer Interrupt Status Register" {
- _ 31 rsvd;
- event_flag 1 rw;
- };
-
- register TimerComparatorLow addr(base, 0x10) "Global Timer Comparator Register (Lower Word)" type(uint32);
- register TimerComparatorHigh addr(base, 0x14) "Global Timer Comparator Register (Upper Word)" type(uint32);
-
- register TimerAutoIncrement addr(base, 0x18) "Global Timer Comparator Auto-Increment Register" type(uint32);
-
- };
+device cortex_a9_gt msbfirst ( addr base ) "Cortex A9 Global Timer" {
+
+ register TimerCounterLow addr(base, 0x0)
+ "Counter (Lower Word)"
+ type(uint32);
+
+ register TimerCounterHigh addr(base, 0x4)
+ "Counter (Upper Word)"
+ type(uint32);
+
+ register TimerControl addr(base, 0x8) "Control" {
+ _ 16 rsvd;
+ prescale 8 rw "Prescale factor";
+ _ 4 rsvd;
+ auto_increment 1 rw "Single shot or increment mode";
+ int_enable 1 rw "Interrupt enable bit";
+ comp_enable 1 rw "Enable comparision between counter and comparator";
+ timer_enable 1 rw "Timer enable bit";
+ };
+
+ register TimerIntStat addr(base, 0xc) "Interrupt Status" {
+ _ 31 rsvd;
+ event_flag 1 rw;
+ };
+
+ register TimerComparatorLow addr(base, 0x10)
+ "Comparator (Lower Word)"
+ type(uint32);
+
+ register TimerComparatorHigh addr(base, 0x14)
+ "Comparator (Upper Word)"
+ type(uint32);
+
+ register TimerAutoIncrement addr(base, 0x18)
+ "Comparator Auto-Increment"
+ type(uint32);
+
+};
--- /dev/null
+/*
+ * Copyright (c) 2012, ETH Zurich. All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+/*
+ * a9scu.dev
+ *
+ * DESCRIPTION: Cortex A9 Snoop Control Unit
+ *
+ * This is derived from:
+ *
+ * ARM Cortex-A9 MPCore Technical Reference Manual
+ *
+ */
+
+device cortex_a9_scu msbfirst ( addr base ) "Cortex A9 SCU" {
+
+ register control addr(base, 0x0) "SCU Control" {
+ _ 25 rsvd;
+ ic_standby 1 rw "IC standby enable";
+ scu_standby 1 rw "SCU standby enable";
+ all_device_to_port0 1 rw "Force all Device to port 0 enable";
+ spec_linefill 1 rw "SCU speculative linefills enable";
+ ram_parity 1 rw "SCU RAMs parity enable";
+ address_filtering 1 rw "Address Filtering enable";
+ enable 1 rw "SCU enable";
+ };
+
+ register config ro addr(base, 0x4) "SCU Configuration" {
+ _ 16;
+ tag_ram_sizes 8 ro "Tag RAM sizes";
+ cpu_smp 4 ro "CPUs SMP bits";
+ _ 2;
+ numcpus 2 ro "Number of CPUs present";
+ };
+
+ constants cpu_status "CPU Status" {
+ normal = 0b00 "Normal mode";
+ dormant = 0b10 "Dormant mode";
+ off = 0b11 "Powered-off mode";
+ };
+
+ register powerstatus addr(base, 0x8) "SCU CPU Power Status" {
+ _ 6;
+ cpu3 2 rw "Status CPU3";
+ _ 6;
+ cpu2 2 rw "Status CPU2";
+ _ 6;
+ cpu1 2 rw "Status CPU1";
+ _ 6;
+ cpu0 2 rw "Status CPU0";
+ };
+
+ register filterstart addr(base, 0x40) "Filtering Start Address" {
+ addr 12 rw "Filtering Start address";
+ _ 20;
+ };
+
+ register filterend addr(base, 0x44) "Filtering End Address" {
+ addr 12 rw "Filtering Start address";
+ _ 20;
+ };
+
+ };
+++ /dev/null
---------------------------------------------------------------------------
--- Copyright (c) 2007-2010, ETH Zurich.
--- All rights reserved.
---
--- This file is distributed under the terms in the attached LICENSE file.
--- If you do not find this file, copies can be found by writing to:
--- ETH Zurich D-INFK, Universitätstasse 6, CH-8092 Zurich. Attn: Systems Group.
---
--- Architectural definitions for Barrelfish on ARMv5 ISA.
---
--- The build target is the integratorcp board on QEMU with the default
--- ARM926EJ-S cpu.
---
---------------------------------------------------------------------------
-
-module ARMv5 where
-
-import HakeTypes
-import qualified Config
-import qualified ArchDefaults
-
--------------------------------------------------------------------------
---
--- Architecture specific definitions for ARMv5
---
--------------------------------------------------------------------------
-
-arch = "armv5"
-archFamily = "arm"
-
-compiler = Config.arm_cc
-objcopy = Config.arm_objcopy
-objdump = Config.arm_objdump
-ar = Config.arm_ar
-ranlib = Config.arm_ranlib
-cxxcompiler = Config.arm_cxx
-
-ourCommonFlags = [ Str "-fno-unwind-tables",
- Str "-Wno-packed-bitfield-compat",
- Str "-mcpu=arm926ej-s",
- Str "-mapcs",
- Str "-mabi=aapcs-linux",
- Str "-msingle-pic-base",
- Str "-mpic-register=r10",
- Str "-DPIC_REGISTER=R10",
- Str "-fpic",
- Str "-ffixed-r9",
- Str "-DTHREAD_REGISTER=R9",
- Str "-D__ARM_ARCH_5__",
- Str "-fno-stack-check",
- Str "-fno-stack-protector",
- Str "-Wno-unused-but-set-variable",
- Str "-Wno-format" ]
-
-cFlags = ArchDefaults.commonCFlags
- ++ ArchDefaults.commonFlags
- ++ ourCommonFlags
-
-cxxFlags = ArchDefaults.commonCxxFlags
- ++ ArchDefaults.commonFlags
- ++ ourCommonFlags
-
-cDefines = ArchDefaults.cDefines options
-
-ourLdFlags = [ Str "-Wl,-section-start,.text=0x400000",
- Str "-Wl,-section-start,.data=0x600000",
- Str "-Wl,--build-id=none" ]
-
-ldFlags = ArchDefaults.ldFlags arch ++ ourLdFlags
-ldCxxFlags = ArchDefaults.ldCxxFlags arch ++ ourLdFlags
-
-stdLibs = ArchDefaults.stdLibs arch
-
-options = (ArchDefaults.options arch archFamily) {
- optFlags = cFlags,
- optCxxFlags = cxxFlags,
- optDefines = cDefines,
- optDependencies =
- [ PreDep InstallTree arch "/include/errors/errno.h",
- PreDep InstallTree arch "/include/barrelfish_kpi/capbits.h",
- PreDep InstallTree arch "/include/asmoffsets.h" ],
- optLdFlags = ldFlags,
- optLdCxxFlags = ldCxxFlags,
- optLibs = stdLibs,
- optInterconnectDrivers = ["lmp"],
- optFlounderBackends = ["lmp"]
- }
-
---
--- Compilers
---
-cCompiler = ArchDefaults.cCompiler arch compiler Config.cOptFlags
-cxxCompiler = ArchDefaults.cxxCompiler arch cxxcompiler Config.cOptFlags
-makeDepend = ArchDefaults.makeDepend arch compiler
-makeCxxDepend = ArchDefaults.makeCxxDepend arch cxxcompiler
-cToAssembler = ArchDefaults.cToAssembler arch compiler Config.cOptFlags
-assembler = ArchDefaults.assembler arch compiler Config.cOptFlags
-archive = ArchDefaults.archive arch
-linker = ArchDefaults.linker arch compiler
-cxxlinker = ArchDefaults.cxxlinker arch cxxcompiler
-
-
---
--- The kernel is "different"
---
-
-kernelCFlags = [ Str s | s <- [ "-fno-builtin",
- "-fno-unwind-tables",
- "-nostdinc",
- "-std=c99",
- "-mcpu=arm926ej-s",
- "-mapcs",
- "-mabi=aapcs-linux",
- "-fPIE",
- "-U__linux__",
- "-Wall",
- "-Wshadow",
- "-Wstrict-prototypes",
- "-Wold-style-definition",
- "-Wmissing-prototypes",
- "-Wmissing-declarations",
- "-Wmissing-field-initializers",
- "-Wredundant-decls",
- "-Werror",
- "-imacros deputy/nodeputy.h",
- "-fpie",
- "-fno-stack-check",
- "-fno-stack-protector",
- "-ffreestanding",
- "-fomit-frame-pointer",
- "-mno-long-calls",
- "-Wmissing-noreturn",
- "-mno-apcs-stack-check",
- "-mno-apcs-reentrant",
- "-msingle-pic-base",
- "-mpic-register=r10",
- "-DPIC_REGISTER=R10",
- "-ffixed-r9",
- "-DTHREAD_REGISTER=R9",
- "-D__ARM_ARCH_5__",
- "-Wno-unused-but-set-variable",
- "-Wno-format" ]]
-
-kernelLdFlags = [ Str "-Wl,-N",
- NStr "-Wl,-Map,", Out arch "kernel.map",
- Str "-fno-builtin",
- Str "-nostdlib",
- Str "-Wl,--fatal-warnings"
- ]
-
-
---
--- Link the kernel (CPU Driver)
---
-linkKernel :: Options -> [String] -> [String] -> String -> HRule
-linkKernel opts objs libs kbin =
- let linkscript = "/kernel/linker.lds"
- kbootable = kbin ++ ".bin"
- in
- Rules [ Rule ([ Str compiler ] ++
- map Str Config.cOptFlags ++
- [ NStr "-T", In BuildTree arch linkscript,
- Str "-o", Out arch kbin
- ]
- ++ (optLdFlags opts)
- ++
- [ In BuildTree arch o | o <- objs ]
- ++
- [ In BuildTree arch l | l <- libs ]
- ++
- (ArchDefaults.kernelLibs arch)
- ),
- -- Edit ELF header so qemu-system-arm will treat it as a Linux kernel
- Rule [ In SrcTree "src" "/tools/arm-mkbootelf.sh",
- Str objdump, In BuildTree arch kbin, Out arch (kbootable)],
- -- Generate kernel assembly dump
- Rule [ Str (objdump ++ " -d -M reg-names-raw"),
- In BuildTree arch kbin, Str ">", Out arch (kbin ++ ".asm")],
- Rule [ Str "cpp",
- NStr "-I", NoDep SrcTree "src" "/kernel/include/arch/armv5",
- Str "-D__ASSEMBLER__",
- Str "-P", In SrcTree "src" "/kernel/arch/armv5/linker.lds.in",
- Out arch linkscript
- ]
- ]
Str "-D__ARM_CORTEX__",
Str "-D__ARM_ARCH_7A__",
Str "-Wno-unused-but-set-variable",
- Str "-Wno-format",
- Str ("-D__" ++ Config.armv7_platform ++ "__")
+ Str "-Wno-format"
]
cFlags = ArchDefaults.commonCFlags
"-D__ARM_CORTEX__",
"-D__ARM_ARCH_7A__",
"-Wno-unused-but-set-variable",
- "-Wno-format",
- "-D__" ++ Config.armv7_platform ++ "__" ]]
+ "-Wno-format" ]]
kernelLdFlags = [ Str "-Wl,-N",
Str "-fno-builtin",
Rule [ Str "cpp",
NStr "-I", NoDep SrcTree "src" "/kernel/include/arch/armv7",
Str "-D__ASSEMBLER__",
- Str ("-D__" ++ Config.armv7_platform ++ "__"),
Str "-P", In SrcTree "src" "/kernel/arch/armv7/linker.lds.in",
Out arch linkscript
]
+++ /dev/null
---------------------------------------------------------------------------
--- Copyright (c) 2007-2010, ETH Zurich.
--- All rights reserved.
---
--- This file is distributed under the terms in the attached LICENSE file.
--- If you do not find this file, copies can be found by writing to:
--- ETH Zurich D-INFK, Universitätstasse 6, CH-8092 Zurich. Attn: Systems Group.
---
--- Architectural definitions for Barrelfish on ARMv7-M ISA.
---
--- The build target is the cortex-m3 sideprocessor on the pandaboard
---------------------------------------------------------------------------
-
-module ARMv7_M where
---module names can not contain "-", so I went for an underscore instead
-import HakeTypes
-import qualified Config
-import qualified ArchDefaults
-import Data.List
-
--------------------------------------------------------------------------
---
--- Architecture specific definitions for ARM
---
--------------------------------------------------------------------------
-
-arch = "armv7-m"
-archFamily = "arm"
-
-compiler = Config.thumb_cc
-objcopy = Config.thumb_objcopy
-objdump = Config.thumb_objdump
-ar = Config.thumb_ar
-ranlib = Config.thumb_ranlib
-cxxcompiler = Config.thumb_cxx
-
-ourCommonFlags = [ Str "-fno-unwind-tables",
- Str "-Wno-packed-bitfield-compat",
- Str "-mthumb",
- Str "-mcpu=cortex-m3",
- Str "-march=armv7-m",
- Str "-mapcs",
- Str "-mabi=aapcs-linux",
- Str "-msingle-pic-base",
- Str "-mpic-register=r10",
- Str "-DPIC_REGISTER=R10",
- Str "-fPIE",
- Str "-ffixed-r9",
- Str "-DTHREAD_REGISTER=R9",
- Str "-D__ARM_CORTEX__",
- Str "-D__ARM_ARCH_7M__",
- Str "-Wno-unused-but-set-variable",
- Str "-Wno-format",
- Str ("-D__" ++ Config.armv7_platform ++ "__")
- ]
-
-cFlags = ArchDefaults.commonCFlags
- ++ ArchDefaults.commonFlags
- ++ ourCommonFlags
-
-cxxFlags = ArchDefaults.commonCxxFlags
- ++ ArchDefaults.commonFlags
- ++ ourCommonFlags
-
-cDefines = ArchDefaults.cDefines options
-
-
-
-ourLdFlags = [ Str "-mcpu=cortex-m3",
- Str "-mthumb", --necessary to get correct division library
- Str "-Wl,-section-start,.text=0x400000",
- Str "-Wl,-section-start,.data=0x600000" ]
-
-
-
-ldFlags = ArchDefaults.ldFlags arch ++ ourLdFlags
-ldCxxFlags = ArchDefaults.ldCxxFlags arch ++ ourLdFlags
-
-stdLibs = ArchDefaults.stdLibs arch
-
-options = (ArchDefaults.options arch archFamily) {
- optFlags = cFlags,
- optCxxFlags = cxxFlags,
- optDefines = cDefines,
- optDependencies =
- [ PreDep InstallTree arch "/include/errors/errno.h",
- PreDep InstallTree arch "/include/barrelfish_kpi/capbits.h",
- PreDep InstallTree arch "/include/asmoffsets.h",
- PreDep InstallTree arch "/include/trace_definitions/trace_defs.h"],
- optLdFlags = ldFlags,
- optLdCxxFlags = ldCxxFlags,
- optLibs = stdLibs,
- optInterconnectDrivers = ["lmp", "ump"],
- optFlounderBackends = ["lmp", "ump"]
- }
-
---
--- Compilers
---
-
--- Heavy optimisation causes GCC to fail with unresolvable register spill.
-v7m_optFlags = (Config.cOptFlags \\ ["-O2", "-O3"]) ++ ["-Os"]
-
-cCompiler = ArchDefaults.cCompiler arch compiler v7m_optFlags
-cxxCompiler = ArchDefaults.cxxCompiler arch cxxcompiler v7m_optFlags
-makeDepend = ArchDefaults.makeDepend arch compiler
-makeCxxDepend = ArchDefaults.makeCxxDepend arch cxxcompiler
-cToAssembler = ArchDefaults.cToAssembler arch compiler v7m_optFlags
-assembler = ArchDefaults.assembler arch compiler v7m_optFlags
-archive = ArchDefaults.archive arch
-linker = ArchDefaults.linker arch compiler
-cxxlinker = ArchDefaults.cxxlinker arch cxxcompiler
-
-
---
--- The kernel is "different"
---
-
-kernelCFlags = [ Str s | s <- [ "-fno-builtin",
- "-fno-unwind-tables",
- "-nostdinc",
- "-std=c99",
- "-mthumb",
- "-mcpu=cortex-m3",
- "-march=armv7-m",
- "-mapcs",
- "-mabi=aapcs-linux",
- "-fPIE",
- "-U__linux__",
- "-Wall",
- "-Wshadow",
- "-Wstrict-prototypes",
- "-Wold-style-definition",
- "-Wmissing-prototypes",
- "-Wmissing-declarations",
- "-Wmissing-field-initializers",
- "-Wredundant-decls",
- "-Werror",
- "-imacros deputy/nodeputy.h",
- "-fno-stack-check",
- "-ffreestanding",
- "-fomit-frame-pointer",
- "-mno-long-calls",
- "-Wmissing-noreturn",
- "-mno-apcs-stack-check",
- "-mno-apcs-reentrant",
- "-msingle-pic-base",
- "-mpic-register=r10",
- "-DPIC_REGISTER=R10",
- "-ffixed-r9",
- "-DTHREAD_REGISTER=R9",
- "-D__ARM_CORTEX__",
- "-D__ARM_ARCH_7M__",
- "-Wno-unused-but-set-variable",
- "-Wno-format",
- "-D__" ++ Config.armv7_platform ++ "__" ]]
-
-kernelLdFlags = [ Str "-Wl,-N",
- Str "-fno-builtin",
- Str "-nostdlib",
- Str "-pie",
- Str "-Wl,--fatal-warnings",
- Str "-mthumb",
- Str "-mcpu=cortex-m3"
- ]---mthumb is necessary to get the correct lgcc (for division)
-
-
---
--- Link the kernel (CPU Driver)
---
-linkKernel :: Options -> [String] -> [String] -> String -> HRule
-linkKernel opts objs libs name =
- let linkscript = "/kernel/" ++ name ++ ".lds"
- kernelmap = "/kernel/" ++ name ++ ".map"
- kasmdump = "/kernel/" ++ name ++ ".asm"
- kbinary = "/sbin/" ++ name
- kbootable = kbinary ++ ".bin"
- in
- Rules [ Rule ([ Str compiler ] ++
- map Str Config.cOptFlags ++
- [ NStr "-T", In BuildTree arch linkscript,
- Str "-o", Out arch kbinary,
- NStr "-Wl,-Map,", Out arch kernelmap
- ]
- ++ (optLdFlags opts)
- ++
- [ In BuildTree arch o | o <- objs ]
- ++
- [ In BuildTree arch l | l <- libs ]
- ++
- (ArchDefaults.kernelLibs arch)
- ),
- -- Generate kernel assembly dump
- Rule [ Str objdump,
- Str "-d",
- Str "-M reg-names-raw",
- In BuildTree arch kbinary,
- Str ">", Out arch kasmdump ],
- Rule [ Str "cpp",
- NStr "-I", NoDep SrcTree "src" "/kernel/include/arch/armv7-m",
- Str "-D__ASSEMBLER__",
- Str ("-D__" ++ Config.armv7_platform ++ "__"),
- Str "-P", In SrcTree "src" "/kernel/arch/armv7-m/linker.lds.in",
- Out arch linkscript
- ]
- ]
sockeyeSchema = []
}
-allArchitectures = [ "x86_64", "x86_32", "armv5", "xscale", "armv7",
- "armv7-m", "armv8", "k1om" ]
+allArchitectures = [ "x86_64", "x86_32", "armv7", "armv8", "k1om" ]
allArchitectureFamilies = [ "x86_64", "x86_32", "arm", "k1om" ]
-- architectures that currently support THC
thcArchitectures = ["x86_64", "x86_32"]
support_qemu_networking :: Bool
support_qemu_networking = False
--- armv7 platform to build for
--- Currently available: gem5, pandaboard
-armv7_platform :: String
---armv7_platform = "gem5"
-armv7_platform = "pandaboard"
-
--- on pandaboard, build a heterogenous image and let the cortex-A9 set up and start the
--- cortex-M3 processor (build targets "heteropanda_slave" and "heteropanda_master_image")
-heteropanda :: Bool
-heteropanda = False
-
-- enable network tracing
trace_network_subsystem :: Bool
trace_network_subsystem = False
lazy_thc :: Bool
lazy_thc
| elem "armv7" architectures = False
- | elem "armv7-m" architectures = False
- | elem "armv5" architectures = False
| elem "armv8" architectures = False
- | elem "xscale" architectures = False
| otherwise = True
-- Enable capability tracing debug facility
if config_svm then "CONFIG_SVM" else "",
if config_arrakismon then "CONFIG_ARRAKISMON" else "",
if use_kaluga_dvm then "USE_KALUGA_DVM" else "",
- if heteropanda then "HETEROPANDA" else "",
if caps_trace then "TRACE_PMEM_CAPS" else ""
], d /= "" ]
Dep InstallTree "" "Config.hs",
Str "$(LDFLAGS)"
]
- ++ [Dep SrcTree "src" f | f <- hakesrc]
- ++ [NL, Str "rm", NoDep BuildTree "hake" "/ARMv5.o" ]),
+ ++ [Dep SrcTree "src" f | f <- hakesrc]),
Rule [ Str "cp",
In SrcTree "src" "symbolic_targets.mk",
Out "root" "symbolic_targets.mk"
import qualified X86_64
import qualified K1om
import qualified X86_32
-import qualified ARMv5
-import qualified XScale
import qualified ARMv7
-import qualified ARMv7_M
import qualified ARMv8
import HakeTypes
import qualified Args
options "x86_64" = X86_64.options
options "k1om" = K1om.options
options "x86_32" = X86_32.options
-options "armv5" = ARMv5.options
-options "xscale" = XScale.options
options "armv7" = ARMv7.options
-options "armv7-m" = ARMv7_M.options
options "armv8" = ARMv8.options
options s = error $ "Unknown architecture " ++ s
kernelCFlags "x86_64" = X86_64.kernelCFlags
kernelCFlags "k1om" = K1om.kernelCFlags
kernelCFlags "x86_32" = X86_32.kernelCFlags
-kernelCFlags "armv5" = ARMv5.kernelCFlags
-kernelCFlags "xscale" = XScale.kernelCFlags
kernelCFlags "armv7" = ARMv7.kernelCFlags
-kernelCFlags "armv7-m" = ARMv7_M.kernelCFlags
kernelCFlags "armv8" = ARMv8.kernelCFlags
kernelCFlags s = error $ "Unknown architecture " ++ s
kernelLdFlags "x86_64" = X86_64.kernelLdFlags
kernelLdFlags "k1om" = K1om.kernelLdFlags
kernelLdFlags "x86_32" = X86_32.kernelLdFlags
-kernelLdFlags "armv5" = ARMv5.kernelLdFlags
-kernelLdFlags "xscale" = XScale.kernelLdFlags
kernelLdFlags "armv7" = ARMv7.kernelLdFlags
-kernelLdFlags "armv7-m" = ARMv7_M.kernelLdFlags
kernelLdFlags "armv8" = ARMv8.kernelLdFlags
kernelLdFlags s = error $ "Unknown architecture " ++ s
| optArch opts == "x86_64" = X86_64.compiler
| optArch opts == "k1om" = K1om.compiler
| optArch opts == "x86_32" = X86_32.compiler
- | optArch opts == "armv5" = ARMv5.compiler
- | optArch opts == "xscale" = XScale.compiler
| optArch opts == "armv7" = ARMv7.compiler
- | optArch opts == "armv7-m" = ARMv7_M.compiler
| optArch opts == "armv8" = ARMv8.compiler
cCompiler :: Options -> String -> String -> String -> [ RuleToken ]
| optArch opts == "x86_64" = X86_64.cCompiler opts phase src obj
| optArch opts == "k1om" = K1om.cCompiler opts phase src obj
| optArch opts == "x86_32" = X86_32.cCompiler opts phase src obj
- | optArch opts == "armv5" = ARMv5.cCompiler opts phase src obj
- | optArch opts == "xscale" = XScale.cCompiler opts phase src obj
| optArch opts == "armv7" = ARMv7.cCompiler opts phase src obj
- | optArch opts == "armv7-m" = ARMv7_M.cCompiler opts phase src obj
| optArch opts == "armv8" = ARMv8.cCompiler opts phase src obj
| otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ]
K1om.makeDepend opts phase src obj depfile
| optArch opts == "x86_32" =
X86_32.makeDepend opts phase src obj depfile
- | optArch opts == "armv5" =
- ARMv5.makeDepend opts phase src obj depfile
- | optArch opts == "xscale" =
- XScale.makeDepend opts phase src obj depfile
| optArch opts == "armv7" =
ARMv7.makeDepend opts phase src obj depfile
- | optArch opts == "armv7-m" =
- ARMv7_M.makeDepend opts phase src obj depfile
| optArch opts == "armv8" =
ARMv8.makeDepend opts phase src obj depfile
| otherwise = [ ErrorMsg ("no dependency generator for " ++ (optArch opts)) ]
| optArch opts == "x86_64" = X86_64.cToAssembler opts phase src afile objdepfile
| optArch opts == "k1om" = K1om.cToAssembler opts phase src afile objdepfile
| optArch opts == "x86_32" = X86_32.cToAssembler opts phase src afile objdepfile
- | optArch opts == "armv5" = ARMv5.cToAssembler opts phase src afile objdepfile
- | optArch opts == "xscale" = XScale.cToAssembler opts phase src afile objdepfile
| optArch opts == "armv7" = ARMv7.cToAssembler opts phase src afile objdepfile
- | optArch opts == "armv7-m" = ARMv7_M.cToAssembler opts phase src afile objdepfile
| optArch opts == "armv8" = ARMv8.cToAssembler opts phase src afile objdepfile
| otherwise = [ ErrorMsg ("no C compiler for " ++ (optArch opts)) ]
| optArch opts == "x86_64" = X86_64.assembler opts src obj
| optArch opts == "k1om" = K1om.assembler opts src obj
| optArch opts == "x86_32" = X86_32.assembler opts src obj
- | optArch opts == "armv5" = ARMv5.assembler opts src obj
- | optArch opts == "xscale" = XScale.assembler opts src obj
| optArch opts == "armv7" = ARMv7.assembler opts src obj
- | optArch opts == "armv7-m" = ARMv7_M.assembler opts src obj
| optArch opts == "armv8" = ARMv8.assembler opts src obj
| otherwise = [ ErrorMsg ("no assembler for " ++ (optArch opts)) ]
| optArch opts == "x86_64" = X86_64.archive opts objs libs name libname
| optArch opts == "k1om" = K1om.archive opts objs libs name libname
| optArch opts == "x86_32" = X86_32.archive opts objs libs name libname
- | optArch opts == "armv5" = ARMv5.archive opts objs libs name libname
- | optArch opts == "xscale" = XScale.archive opts objs libs name libname
| optArch opts == "armv7" = ARMv7.archive opts objs libs name libname
- | optArch opts == "armv7-m" = ARMv7_M.archive opts objs libs name libname
| optArch opts == "armv8" = ARMv8.archive opts objs libs name libname
| otherwise = [ ErrorMsg ("Can't build a library for " ++ (optArch opts)) ]
| optArch opts == "x86_64" = X86_64.linker opts objs libs bin
| optArch opts == "k1om" = K1om.linker opts objs libs bin
| optArch opts == "x86_32" = X86_32.linker opts objs libs bin
- | optArch opts == "armv5" = ARMv5.linker opts objs libs bin
- | optArch opts == "xscale" = XScale.linker opts objs libs bin
| optArch opts == "armv7" = ARMv7.linker opts objs libs bin
- | optArch opts == "armv7-m" = ARMv7_M.linker opts objs libs bin
| optArch opts == "armv8" = ARMv8.linker opts objs libs bin
| otherwise = [ ErrorMsg ("Can't link executables for " ++ (optArch opts)) ]
| optArch opts == "x86_64" = X86_64.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" </> name)
| optArch opts == "k1om" = K1om.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" </> name)
| optArch opts == "x86_32" = X86_32.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" </> name)
- | optArch opts == "armv5" = ARMv5.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" </> name)
- | optArch opts == "xscale" = XScale.linkKernel opts objs [libraryPath l | l <- libs ] ("/sbin" </> name)
| optArch opts == "armv7" = ARMv7.linkKernel opts objs [libraryPath l | l <- libs ] name
- | optArch opts == "armv7-m" = ARMv7_M.linkKernel opts objs [libraryPath l | l <- libs ] name
| optArch opts == "armv8" = ARMv8.linkKernel opts objs [libraryPath l | l <- libs ] name
| otherwise = Rule [ Str ("Error: Can't link kernel for '" ++ (optArch opts) ++ "'") ]
+++ /dev/null
---------------------------------------------------------------------------
--- Copyright (c) 2007-2015, ETH Zurich.
--- All rights reserved.
---
--- This file is distributed under the terms in the attached LICENSE file.
--- If you do not find this file, copies can be found by writing to:
--- ETH Zurich D-INFK, Universitätstasse 6, CH-8092 Zurich. Attn: Systems Group.
---
--- Architectural definitions for Barrelfish on ARMv5 ISA.
---
--- The build target is the XScale with XScale cpu.
---
---------------------------------------------------------------------------
-
-module XScale where
-
-import HakeTypes
-import qualified Config
-import qualified ArchDefaults
-
--------------------------------------------------------------------------
---
--- Architecture specific definitions for ARM
---
--------------------------------------------------------------------------
-
-arch = "xscale"
-archFamily = "arm"
-
-compiler = Config.armeb_cc
-objcopy = Config.armeb_objcopy
-objdump = Config.armeb_objdump
-ar = Config.armeb_ar
-ranlib = Config.armeb_ranlib
-cxxcompiler = Config.armeb_cxx
-
-ourCommonFlags = [ Str "-Wno-packed-bitfield-compat",
- Str "-Wno-format",
- Str "-fno-unwind-tables",
- Str "-fshort-enums",
- Str "-mcpu=xscale",
- Str "-mbig-endian",
- Str "-mapcs",
- Str "-mabi=aapcs-linux",
- Str "-msingle-pic-base",
- Str "-mpic-register=r10",
- Str "-DPIC_REGISTER=R10",
- Str "-fpic",
- Str "-ffixed-r9",
- Str "-DTHREAD_REGISTER=R9",
- Str "-D__ARM_ARCH_5__" ]
-
-cFlags = ArchDefaults.commonCFlags
- ++ ArchDefaults.commonFlags
- ++ ourCommonFlags
-
-cxxFlags = ArchDefaults.commonCxxFlags
- ++ ArchDefaults.commonFlags
- ++ ourCommonFlags
-
-cDefines = ArchDefaults.cDefines options
-
-ourLdFlags = [ Str "-Wl,-section-start,.text=0x400000",
- Str "-Wl,-section-start,.data=0x600000",
- Str "-mcpu=xscale",
- Str "-mbig-endian" ]
-
-ldFlags = ArchDefaults.ldFlags arch ++ ourLdFlags
-ldCxxFlags = ArchDefaults.ldCxxFlags arch ++ ourLdFlags
-
-stdLibs = ArchDefaults.stdLibs arch
-
-options = (ArchDefaults.options arch archFamily) {
- optFlags = cFlags,
- optCxxFlags = cxxFlags,
- optDefines = cDefines,
- optDependencies =
- [ PreDep BuildTree arch "/include/errors/errno.h",
- PreDep InstallTree arch "/include/barrelfish_kpi/capbits.h",
- PreDep InstallTree arch "/include/asmoffsets.h",
- PreDep InstallTree arch "/include/romfs_size.h" ],
- optLdFlags = ldFlags,
- optLdCxxFlags = ldCxxFlags,
- optLibs = stdLibs,
- optInterconnectDrivers = ["lmp"],
- optFlounderBackends = ["lmp"]
- }
-
-
---
--- Compilers
---
-cCompiler = ArchDefaults.cCompiler arch compiler Config.cOptFlags
-cxxCompiler = ArchDefaults.cxxCompiler arch cxxcompiler Config.cOptFlags
-makeDepend = ArchDefaults.makeDepend arch compiler
-makeCxxDepend = ArchDefaults.makeCxxDepend arch cxxcompiler
-cToAssembler = ArchDefaults.cToAssembler arch compiler Config.cOptFlags
-assembler = ArchDefaults.assembler arch compiler Config.cOptFlags
-archive = ArchDefaults.archive arch
-linker = ArchDefaults.linker arch compiler
-cxxlinker = ArchDefaults.cxxlinker arch cxxcompiler
-
---
--- The kernel is "different"
---
-
-kernelCFlags = [ Str s | s <- [ "-fno-builtin",
- "-fno-unwind-tables",
- "-fshort-enums",
- "-nostdinc",
- "-std=c99",
- "-mcpu=xscale",
- "-mbig-endian",
- "-mapcs",
- "-mabi=aapcs-linux",
- "-fPIE",
- "-U__linux__",
- "-Wall",
- "-Wshadow",
- "-Wstrict-prototypes",
- "-Wold-style-definition",
- "-Wmissing-prototypes",
- "-Wmissing-declarations",
- "-Wmissing-field-initializers",
- "-Wno-implicit-function-declaration",
- "-Wredundant-decls",
- "-Werror",
- "-imacros deputy/nodeputy.h",
- "-fpie",
- "-fno-stack-check",
- "-ffreestanding",
- "-fomit-frame-pointer",
- "-mno-long-calls",
- "-Wno-missing-noreturn",
- "-Wno-format",
- "-mno-apcs-stack-check",
- "-mno-apcs-reentrant",
- "-msingle-pic-base",
- "-mpic-register=r10",
- "-DPIC_REGISTER=R10",
- "-ffixed-r9",
- "-DTHREAD_REGISTER=R9",
- "-D__ARM_ARCH_5__" ]]
-
-kernelLdFlags = [ Str "-Wl,-N",
- NStr "-Wl,-Map,", Out arch "kernel.map",
- Str "-fno-builtin",
- Str "-nostdlib",
- Str "-Wl,--fatal-warnings",
- Str "-mcpu=xscale",
- Str "-mbig-endian"
- ]
-
-
---
--- Link the kernel (CPU Driver)
---
-linkKernel :: Options -> [String] -> [String] -> String -> HRule
-linkKernel opts objs libs kbin =
- let linkscript = "/kernel/linker.lds"
- kbootable = kbin ++ ".bin"
- in
- Rules [ Rule ([ Str compiler ] ++
- map Str Config.cOptFlags ++
- [ NStr "-T", In BuildTree arch linkscript,
- Str "-o", Out arch kbin
- ]
- ++ (optLdFlags opts)
- ++
- [ In BuildTree arch o | o <- objs ]
- ++
- [ In BuildTree arch l | l <- libs ]
- ++
- (ArchDefaults.kernelLibs arch)
- ),
- -- Edit ELF header so qemu-system-arm will treat it as a Linux kernel
- Rule [ In SrcTree "src" "/tools/arm-mkbootelf.sh",
- Str objdump, In BuildTree arch kbin, Out arch (kbootable)],
- -- Generate kernel assembly dump
- Rule [ Str (objdump ++ " -d -M reg-names-raw"),
- In SrcTree arch kbin, Str ">", Out arch (kbin ++ ".asm")],
- Rule [ Str "cpp",
- NStr "-I", NoDep SrcTree "src" "/kernel/include/arch/xscale",
- Str "-D__ASSEMBLER__",
- Str "-P", In SrcTree "src" "/kernel/arch/xscale/linker.lds.in",
- Out arch linkscript
- ]
- ]
echo " argument specifying the top of the source tree."
echo ""
echo " Known architectures may include: "
- echo " x86_64 x86_32 armv5 xscale armv7 armv7-m k10m"
+ echo " x86_64 x86_32 armv7 armv8 k10m"
exit 1;
}
+++ /dev/null
-timeout 0
-
-#
-# This script is used to describe the commands to start at
-# boot-time and the arguments they should receive.
-#
-# Kernel arguments are not read from this script. On QEMU they can be
-# set using 'qemu-system-arm -append ...'.
-
-title Barrelfish
-#root (nd)
-#kernel /arm/sbin/cpu loglevel=4
-module /armv5/sbin/cpu
-module /armv5/sbin/init
-
-# Domains spawned by init
-module /armv5/sbin/mem_serv
-module /armv5/sbin/monitor
-
-# Special boot time domains spawned by monitor
-module /armv5/sbin/ramfsd boot
-module /armv5/sbin/skb boot
-module /armv5/sbin/spawnd boot bootarm
-module /armv5/sbin/startd boot
-
-# General user domains
-#module /armv5/sbin/serial
-#module /armv5/sbin/fish
-
-module /armv5/sbin/memtest
+++ /dev/null
-timeout 0
-
-#
-# This script is used to describe the commands to start at
-# boot-time and the arguments they should receive.
-#
-
-title Barrelfish
-#root (nd)
-kernel /armv7-m/sbin/cpu_omap44xx loglevel=4
-module /armv7-m/sbin/cpu_omap44xx
-module /armv7-m/sbin/init
-
-# Domains spawned by init
-module /armv7-m/sbin/mem_serv
-module /armv7-m/sbin/monitor
-
-# Special boot time domains spawned by monitor
-#module /armv7-m/sbin/chips boot
-module /armv7-m/sbin/ramfsd boot
-module /armv7-m/sbin/skb boot
-module /armv7-m/sbin/spawnd boot bootarm=0
-module /armv7-m/sbin/startd boot
-
-# General user domains
-#module /armv7-m/sbin/serial
-#module /armv7-m/sbin/fish
-
-module /armv7-m/sbin/memtest
-
-# start at 0x90000000, because 0xA0000000 is statically marked as no-execute
-mmap map 0x90000000 0x30000000 1
+++ /dev/null
-timeout 0
-
-#
-# This script is used to describe the commands to start at
-# boot-time and the arguments they should receive.
-#
-# Kernel arguments are not read from this script. On QEMU they can be
-# set using 'qemu-system-arm -append ...'.
-
-title Barrelfish
-#root (nd)
-#kernel /xscale/sbin/cpu loglevel=4
-module /xscale/sbin/cpu
-module /xscale/sbin/init
-
-# Domains spawned by init
-module /xscale/sbin/mem_serv
-module /xscale/sbin/monitor
-
-# Special boot time domains spawned by monitor
-module /xscale/sbin/ramfsd boot
-module /xscale/sbin/skb boot
-module /xscale/sbin/spawnd boot bootarm
-module /xscale/sbin/startd boot
-
-# General user domains
-#module /xscale/sbin/serial
-#module /xscale/sbin/fish
-
-#module /xscale/sbin/memtest
sbin/sshd \
sbin/corectrl
-# ARM-specific modules to build by default
-MODULES_armv5=\
- sbin/cpu \
- sbin/cpu.bin
-
-# XScale-specific modules to build by default
-MODULES_xscale=\
- sbin/cpu_ixp2800 \
- sbin/cpu_ixp2800.bin
-
# ARMv7-specific modules to build by default
# XXX: figure out armv7 default
MODULES_armv7=\
#define CURRENT_CPU_TYPE CPU_ARM7
#elif __ARM_ARCH_7M__
#define CURRENT_CPU_TYPE CPU_ARM7
-#elif __ARM_ARCH_5__
-#define CURRENT_CPU_TYPE CPU_ARM5
#elif __ARM_ARCH_8A__
#define CURRENT_CPU_TYPE CPU_ARM8
#else
/**
* \file
- * \brief
+ * \brief Very simple ARMv7a spinlocks
+ *
+ * Not exactly scalable, but serviceable for infrequent use (e.g. in
+ * the kernel for arbitrating the console UART).
+ *
+ * We let the compiler do the heavy lifting here wrt. the memory model.
*/
/*
- * Copyright (c) 2010, ETH Zurich.
+ * Copyright (c) 2010-2016, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ * ETH Zurich D-INFK, CAB F.78, Universitaestr. 6, CH-8092 Zurich.
+ * Attn: Systems Group.
*/
#ifndef ARCH_ARM_BARRELFISH_KPI_SPINLOCKS_H
#define ARCH_ARM_BARRELFISH_KPI_SPINLOCKS_H
-#include <barrelfish_kpi/asm_inlines_arch.h>
-
-typedef volatile uint32_t spinlock_t;
+/* Need to include this for errval_t */
+#include <errors/errno.h>
+#include <stdbool.h>
-#ifdef __ARM_ARCH_7A__
-
-static inline void acquire_spinlock(spinlock_t *spinlock)
-{
- unsigned long tmp;
+typedef bool spinlock_t;
- __asm volatile (
- "1: ldrex %0, [%1]\n\t"
- "teq %0, #0\n\t"
- "wfene\n\t"
- "strexeq %0, %2, [%1]\n\t"
- "teqeq %0, #0\n\t"
- "bne 1b"
- : "=&r" (tmp)
- : "r" (spinlock), "r" (1)
- : "cc");
- dmb();
-}
-
-static inline void release_spinlock(spinlock_t *spinlock)
+/*
+ * Initialize a spinlock
+ */
+static inline void spinlock_init(spinlock_t *l)
{
- dmb();
-
- __asm volatile (
- "str %1, [%0]\n\t"
- "sev\n\t"
- :
- : "r" (spinlock), "r" (0)
- : "cc");
+ __atomic_clear(l, __ATOMIC_RELEASE);
}
-#else
-
-static inline void acquire_spinlock(spinlock_t *spinlock)
+/*
+ * acquire and release specific locks
+ * chosen the names as a contrast to "acquire_spinlock", because the arguments differ
+ * (here we want the index of the lock in the module, instead of a generic address)
+ */
+#define acquire_spinlock(_l) spinlock_acquire(_l)
+static inline void spinlock_acquire(spinlock_t *l)
{
+ while (__atomic_test_and_set(l, __ATOMIC_ACQUIRE));
}
-static inline void release_spinlock(spinlock_t *spinlock)
+#define release_spinlock(_l) spinlock_release(_l)
+static inline void spinlock_release(spinlock_t *l)
{
+ __atomic_clear(l, __ATOMIC_RELEASE);
}
-#endif //__ARM_ARCH_7A__
-
#endif // ARCH_ARM_BARRELFISH_KPI_SPINLOCKS_H
#define OMAP44XX_CAM_CM2 0x4A009000
#define OMAP44XX_CAM_PRM 0x4A307000
-#define OMAP44XX_FDIF 0x4A10A000
#define OMAP44XX_CM2 0x4A009300
#define OMAP44XX_CLKGEN_CM2 0x4A008100
#define OMAP44XX_L4PER_CM2 0x4A009400
#define OMAP44XX_DEVICE_PRM 0x4A307B00
-#define OMAP44XX_INTRCONN_SOCKET_PRM 0x4A306000
-
-// 256 BYTES
-#define OMAP44XX_I2C3 0x48060000
-#define OMAP44XX_I2C1 0x48070000
-#define OMAP44XX_I2C2 0x48072000
-#define OMAP44XX_I2C4 0x48350000
-
-// 4K BYTES
-#define OMAP44XX_SYSCTRL_GENERAL_CORE 0x4A002000
-#define OMAP44XX_SYSCTRL_GENERAL_WAKEUP 0x4A30C000
-#define OMAP44XX_SYSCTRL_PADCONF_CORE 0x4A100000
-#define OMAP44XX_SYSCTRL_PADCONF_WAKEUP 0x4A31E000
-
-#define OMAP44XX_HSUSBHOST 0x4A064000
-
-// 4KB BYTES
-#define OMAP44XX_MMCHS1 0x4809C000
-#define OMAP44XX_MMCHS2 0x480B4000
-#define OMAP44XX_MMCHS3 0x480AD000
-#define OMAP44XX_MMCHS4 0x480D1000
-#define OMAP44XX_MMCHS5 0x480D5000
-
-// UARTs
-#define OMAP44XX_MAP_L4_PER_UART1 0x4806A000
-#define OMAP44XX_MAP_L4_PER_UART1_SIZE 0x1000
-#define OMAP44XX_MAP_L4_PER_UART2 0x4806C000
-#define OMAP44XX_MAP_L4_PER_UART2_SIZE 0x1000
-#define OMAP44XX_MAP_L4_PER_UART3 0x48020000
-#define OMAP44XX_MAP_L4_PER_UART3_SIZE 0x1000
-#define OMAP44XX_MAP_L4_PER_UART4 0x4806E000
-#define OMAP44XX_MAP_L4_PER_UART4_SIZE 0x1000
-
-// 4KB BYTES
-#define OMAP44XX_SDMA 0x4A056000
#endif // DEVICE_REGISTERS_H_
return (lvaddr_t)handle;
}
+#include <stdio.h>
+static inline void dump_dispatcher(struct dispatcher_shared_generic *disp)
+{
+ printf("Dump of dispatcher at address %p:\n", disp);
+ printf(" disabled = %d (%s)\n", disp->disabled, disp->disabled ? "RESUME" : "UPCALL" );
+ printf(" haswork = %d\n", disp->haswork );
+ printf(" udisp = 0x%"PRIxLVADDR"\n", disp->udisp );
+ printf(" lmp_delivered = %d\n", disp->lmp_delivered );
+ printf(" lmp_seen = %d\n", disp->lmp_seen );
+ printf(" lpm_hint = 0x%"PRIxLVADDR"\n", disp->lmp_hint );
+ printf(" dispatcher_run = 0x%"PRIxLVADDR"\n", disp->dispatcher_run );
+ printf(" dispatcher_pagefault = 0x%"PRIxLVADDR"\n", disp->dispatcher_pagefault );
+ printf(" dispatcher_pagefault_disabled = 0x%"PRIxLVADDR"\n", disp->dispatcher_pagefault_disabled );
+ printf(" dispatcher_trap = 0x%"PRIxLVADDR"\n", disp->dispatcher_trap );
+ printf(" systime = 0x%lx\n", disp->systime );
+ printf(" wakeup = 0x%lx\n", disp->wakeup );
+ printf(" name = %s\n", disp->name );
+ printf(" fpu_used = %d\n", disp->fpu_used );
+ printf(" fpu_trap = %d\n", disp->fpu_trap );
+ printf(" curr_core_id = 0x%x\n", disp->curr_core_id );
+}
+
+
#endif //__ASSEMBLER__
#endif // BARRELFISH_KPI_DISPATCHER_SHARED_H
#define OMAP44XX_MAP_SDRAM 0x80000000
/*
+ * 4.4 Dual Cortex-A9 MPU Subsystem Registers
+ */
+#define OMAP44XX_MAP_CORTEXA9_SCU 0x48240000
+#define OMAP44XX_MAP_CORTEXA9_SCU_SIZE 0x80
+#define OMAP44XX_MAP_CORTEXA9_GICPROC 0x48240100
+#define OMAP44XX_MAP_CORTEXA9_GICPROC_SIZE 0x100
+#define OMAP44XX_MAP_CORTEXA9_TIMER 0x48240600
+#define OMAP44XX_MAP_CORTEXA9_TIMER_SIZE 0x100
+#define OMAP44XX_MAP_CORTEXA9_GICDIST 0x48241000
+#define OMAP44XX_MAP_CORTEXA9_GICDIST_SIZE 0x1000
+#define OMAP44XX_MAP_CORTEXA9_PL310 0x48242000
+#define OMAP44XX_MAP_CORTEXA9_PL310_SIZE 0x1000
+#define OMAP44XX_MAP_CORTEXA9_SOCKET_PRCM 0x48243000
+#define OMAP44XX_MAP_CORTEXA9_SOCKET_PRCM_SIZE 0x200
+#define OMAP44XX_MAP_CORTEXA9_PRM 0x48243200
+#define OMAP44XX_MAP_CORTEXA9_PRM_SIZE 0x200
+#define OMAP44XX_MAP_CORTEXA9_CPU0 0x48243400
+#define OMAP44XX_MAP_CORTEXA9_CPU0_SIZE 0x400
+#define OMAP44XX_MAP_CORTEXA9_CPU1 0x48243800
+#define OMAP44XX_MAP_CORTEXA9_CPU1_SIZE 0x400
+#define OMAP44XX_MAP_CORTEXA9_WUGEN 0x48281000
+#define OMAP44XX_MAP_CORTEXA9_WUGEN_SIZE 0x1000
+#define OMAP44XX_MAP_CORTEXA9_CMU 0x48290000
+#define OMAP44XX_MAP_CORTEXA9_CMU_SIZE 0x10000
+#define OMAP44XX_MAP_CORTEXA9_LOCAL 0x482A0000
+#define OMAP44XX_MAP_CORTEXA9_LOCAL_SIZE 0x1000
+#define OMAP44XX_MAP_CORTEXA9_MA 0x482AF000
+#define OMAP44XX_MAP_CORTEXA9_MA_SIZE 0x1000
+
+
+/*
* 15.3 External memory interface
*/
#define OMAP44XX_MAP_EMIF1 0x4c000000
#define LARGE_PAGE_MASK (LARGE_PAGE_SIZE - 1)
#define LARGE_PAGE_OFFSET(a) ((a) & LARGE_PAGE_MASK)
-#define ARM_L1_OFFSET(addr) (((uintptr_t)addr) >> 20)
+#define ARM_L1_OFFSET(addr) ((((uintptr_t)addr) >> 20) & 0xfff)
#define ARM_L2_OFFSET(addr) ((((uintptr_t)addr) >> 12) & 0xff)
#define ARM_PAGE_OFFSET(addr) ((uintptr_t)addr & 0xfff)
-#define ARM_L1_ALIGN 16384u
#define ARM_L1_MAX_ENTRIES 4096u
#define ARM_L1_BYTES_PER_ENTRY 4u
-#define ARM_L1_SECTION_BYTES (1024u * 1024u)
-#define ARM_L1_SECTION_MASK 0x000FFFFF
+#define ARM_L1_ALIGN 16384u
+#define ARM_L1_SECTION_BITS 20u
+#define ARM_L1_SECTION_BYTES (1u << ARM_L1_SECTION_BITS)
+#define ARM_L1_SECTION_MASK (ARM_L1_SECTION_BYTES - 1u)
+#define ARM_L1_SECTION_OFFSET(a) ((a) & ARM_L1_SECTION_MASK)
+#define ARM_L1_SECTION_NUMBER(a) ((a) >> ARM_L1_SECTION_BITS)
+
-#define ARM_L2_ALIGN 1024u
#define ARM_L2_MAX_ENTRIES 256u
#define ARM_L2_BYTES_PER_ENTRY 4u
-#define ARM_L2_TABLE_BYTES ARM_L2_ALIGN
+#define ARM_L2_ALIGN 1024u
+#define ARM_L2_TABLE_BITS 10u
+#define ARM_L2_TABLE_BYTES (1 << ARM_L2_TABLE_BITS)
+#define ARM_L2_TABLE_MASK (ARM_L2_TABLE_BYTES - 1u)
+#define ARM_L2_TABLE_OFFSET(a) ((a) & ARM_L2_TABLE_MASK)
+#define ARM_L2_TABLE_PPN(a) ((a) >> ARM_L2_TABLE_BITS)
#define ARM_L2_SMALL_CACHEABLE 0x008
#define ARM_L2_SMALL_BUFFERABLE 0x004
uint32_t ap2 :1; // AP[2]
uint32_t shareable :1;
uint32_t not_global :1;
- uint32_t mbo0 :1; //must be one
+ uint32_t mbz0 :1; //must be one
uint32_t ns :1;
uint32_t base_address :12;
} super_section;
#define L2_TYPE_SMALL_PAGE_XN 3
#define L2_TYPE(x) ((x) & 3)
-#define BYTES_PER_SECTION 0x100000
+#define BYTES_PER_SECTION ARM_L1_SECTION_BYTES
#define BYTES_PER_LARGE_PAGE 0x10000
#define BYTES_PER_PAGE 0x1000
-#define BYTES_PER_SMALL_PAGE 0x400
+#define BYTES_PER_SMALL_PAGE ARM_L2_TABLE_BYTES
#endif // TARGET_ARM_BARRELFISH_KPI_PAGING_ARM_V7_H
--- /dev/null
+/**
+ * \file
+ * \brief Physical memory map for TI OMAP 44xx-series SoCs.
+ *
+ * This is derived from:
+ *
+ * OMAP4430 Multimedia Device Silicon Revision 2.x Technical Reference
+ * Manual Version O
+ * OMAP4460 Multimedia Device Silicon Revision 1.x Technical Reference
+ * Manual Version Q
+ *
+ * Section numbers refer to the OMAP4460 TRM.
+ */
+
+/*
+ * Copyright (c) 2012, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, CAB F.78, Universitaetstr. 6, CH-8092 Zurich.
+ * Attn: Systems Group.
+ */
+
+#ifndef VEXPRESS_MAP_H
+#define VEXPRESS_MAP_H
+
+
+/*
+ * For more information, see the ARM Motherboard Express μATX
+ * Technical Reference Manual V2M-P1. Section numbers below refer to this.
+ */
+
+/*
+ * Chip select addresses: see S.4.2.2. This is the setup used by the
+ * CoreTile Express A15x2 daughterboard, which is what GEM5 seems to
+ * be emulating (mostly).
+ */
+#define VEXPRESS_MAP_CS0 0x00000000
+#define VEXPRESS_MAP_CS1 0x14000000
+#define VEXPRESS_MAP_CS2 0x18000000
+#define VEXPRESS_MAP_CS3 0x1C000000
+#define VEXPRESS_MAP_CS4 0x0C000000
+#define VEXPRESS_MAP_CS5 0x10000000
+
+#define VEXPRESS_MAP_NOR_FLASH_0 (VEXPRESS_MAP_CS0 + 0)
+#define VEXPRESS_MAP_NOR_FLASH_0_SIZE 0x4000000
+#define VEXPRESS_MAP_NOR_FLASH_1 (VEXPRESS_MAP_CS4 + 0)
+#define VEXPRESS_MAP_NOR_FLASH_1_SIZE 0x4000000
+#define VEXPRESS_MAP_USER_SRAM (VEXPRESS_MAP_CS1 + 0)
+#define VEXPRESS_MAP_USER_SRAM_SIZE 0x4000000
+#define VEXPRESS_MAP_VRAM (VEXPRESS_MAP_CS2 + 0)
+#define VEXPRESS_MAP_VRAM_SIZE 0x2000000
+#define VEXPRESS_MAP_LAN (VEXPRESS_MAP_CS2 + 0x02000000)
+#define VEXPRESS_MAP_LAN_SIZE 0x10000
+#define VEXPRESS_MAP_USB (VEXPRESS_MAP_CS2 + 0x03000000)
+#define VEXPRESS_MAP_USB_SIZE 0x20000
+
+#define VEXPRESS_MAP_DAP_ROM (VEXPRESS_MAP_CS3 + 0x00000000)
+#define VEXPRESS_MAP_DAP_ROM_SIZE 0x10000
+#define VEXPRESS_MAP_SYSREG (VEXPRESS_MAP_CS3 + 0x00010000)
+#define VEXPRESS_MAP_SYSREG_SIZE 0x10000
+#define VEXPRESS_MAP_SP810 (VEXPRESS_MAP_CS3 + 0x00020000)
+#define VEXPRESS_MAP_SP810_SIZE 0x10000
+#define VEXPRESS_MAP_SERIAL_PCI (VEXPRESS_MAP_CS3 + 0x00030000)
+#define VEXPRESS_MAP_SERIAL_PCI_SIZE 0x10000
+#define VEXPRESS_MAP_AACI (VEXPRESS_MAP_CS3 + 0x00040000) // PL041
+#define VEXPRESS_MAP_AACI_SIZE 0x10000
+#define VEXPRESS_MAP_MMCI (VEXPRESS_MAP_CS3 + 0x00050000) // PL180
+#define VEXPRESS_MAP_MMCI_SIZE 0x10000
+#define VEXPRESS_MAP_KMI0 (VEXPRESS_MAP_CS3 + 0x00060000) // PL050
+#define VEXPRESS_MAP_KMI0_SIZE 0x10000
+#define VEXPRESS_MAP_KMI1 (VEXPRESS_MAP_CS3 + 0x00070000) // PL050
+#define VEXPRESS_MAP_KMI1_SIZE 0x10000
+#define VEXPRESS_MAP_ENERGY_CTRL (VEXPRESS_MAP_CS3 + 0x00080000) // ??? GEM5
+#define VEXPRESS_MAP_ENERGY_CTRL_SIZE 0x10000
+#define VEXPRESS_MAP_UART0 (VEXPRESS_MAP_CS3 + 0x00090000) // PL011
+#define VEXPRESS_MAP_UART0_SIZE 0x10000
+#define VEXPRESS_MAP_UART1 (VEXPRESS_MAP_CS3 + 0x000A0000) // PL011
+#define VEXPRESS_MAP_UART1_SIZE 0x10000
+#define VEXPRESS_MAP_UART2 (VEXPRESS_MAP_CS3 + 0x000B0000) // PL011
+#define VEXPRESS_MAP_UART2_SIZE 0x10000
+#define VEXPRESS_MAP_UART3 (VEXPRESS_MAP_CS3 + 0x000C0000) // PL011
+#define VEXPRESS_MAP_UART3_SIZE 0x10000
+#define VEXPRESS_MAP_WATCHDOG (VEXPRESS_MAP_CS3 + 0x000F0000) // SP805
+#define VEXPRESS_MAP_WATCHDOG_SIZE 0x10000
+#define VEXPRESS_MAP_TIMER01 (VEXPRESS_MAP_CS3 + 0x00110000) // SP801
+#define VEXPRESS_MAP_TIMER01_SIZE 0x10000
+#define VEXPRESS_MAP_TIMER23 (VEXPRESS_MAP_CS3 + 0x00120000) // SP801
+#define VEXPRESS_MAP_TIMER23_SIZE 0x10000
+#define VEXPRESS_MAP_RTC (VEXPRESS_MAP_CS3 + 0x00170000) // PL031
+#define VEXPRESS_MAP_RTC_SIZE 0x10000
+#define VEXPRESS_MAP_IDE_BAR0 (VEXPRESS_MAP_CS3 + 0x001A0000) // ??? GEM5
+#define VEXPRESS_MAP_IDE_BAR0_SIZE 0x100
+#define VEXPRESS_MAP_IDE_BAR1 (VEXPRESS_MAP_CS3 + 0x001A0100) // ??? GEM5
+#define VEXPRESS_MAP_IDE_BAR1_SIZE 0x1000
+#define VEXPRESS_MAP_UART4 (VEXPRESS_MAP_CS3 + 0x001B0000) // PL011
+#define VEXPRESS_MAP_UART4_SIZE 0x10000
+#define VEXPRESS_MAP_CLCD (VEXPRESS_MAP_CS3 + 0x001F0000) // PL111
+#define VEXPRESS_MAP_CLCD_SIZE 0x10000
+
+/*
+ * This is the daughterboard memory map
+ *
+ * For this, see the CoreTile Expressâ„¢ A15x2 Cortexâ„¢-A15 MPCore
+ * (V2P-CA15) Technical Reference Manual, S.3.2.3
+ */
+
+#define VEXPRESS_MAP_CORESIGHT 0x20000000
+#define VEXPRESS_MAP_CORESIGHT_SIZE 0x8000000
+#define VEXPRESS_MAP_AXI_NIC 0x2A000000
+#define VEXPRESS_MAP_AXI_NIC_SIZE 0x100000 // NIC-301
+#define VEXPRESS_MAP_SCC 0x2A420000
+#define VEXPRESS_MAP_SCC_SIZE 0x10000
+#define VEXPRESS_MAP_SYS_COUNT 0x2A430000
+#define VEXPRESS_MAP_SYS_COUNT_SIZE 20
+#define VEXPRESS_MAP_HDLCD 0x2B000000
+#define VEXPRESS_MAP_HDLCD_SIZE 592
+#define VEXPRESS_MAP_SYS_WDG 0x2B060000 // SP805 (not same as above)
+#define VEXPRESS_MAP_SYS_WDG_SIZE 0x1000
+#define VEXPRESS_MAP_DMC_CONFIG 0x2B0A0000 // PL341
+#define VEXPRESS_MAP_DMC_CONFIG_SIZE 0x1000
+#define VEXPRESS_MAP_GIC_DIST 0x2C001000 // PL130
+#define VEXPRESS_MAP_GIC_DIST_SIZE 0x1000
+#define VEXPRESS_MAP_GIC_CPU 0x2C002000 // PL130
+#define VEXPRESS_MAP_GIC_CPU_SIZE 0x100
+#define VEXPRESS_MAP_VGIC_HV 0x2C004000
+#define VEXPRESS_MAP_VGIC_HV_SIZE 0x1000
+#define VEXPRESS_MAP_VGIC_VCPU 0x2C006000
+#define VEXPRESS_MAP_VGIC_VCPU_SIZE 0x1000
+#define VEXPRESS_MAP_LOCAL_CPU_TIMER 0x2C080000
+#define VEXPRESS_MAP_LOCAL_CPU_TIMER_SIZE 0x1000
+#define VEXPRESS_MAP_L2X0 0x2C100000
+#define VEXPRESS_MAP_L2X0_SIZE 0x1000)
+
+#define VEXPRESS_MAP_PCI_CFG 0x30000000
+#define VEXPRESS_MAP_PCI_CFG_SIZE 0x10000000
+
+#endif // VEXPRESS_MAP_H
addLibraries = [ "elf_kernel" ]
},
--
- -- Generic ARMv5 core, unused?
- --
- cpuDriver {
- architectures = [ "armv5" ],
- assemblyFiles = [ "arch/armv5/boot.S",
- "arch/armv5/exceptions.S" ],
- cFiles = [ "arch/arm/exn.c",
- "arch/arm/exec.c",
- "arch/arm/misc.c",
- "arch/arm/dispatch.c",
- "arch/armv5/phys_mmap.c",
- "arch/arm/syscall.c",
- "arch/armv5/init.c",
- "arch/armv5/integrator.c",
- "arch/armv5/kludges.c",
- "arch/arm/kputchar.c",
- "arch/arm/pl011_uart.c",
- "arch/armv5/cp15.c",
- "arch/armv5/paging.c",
- "arch/armv5/startup_arch.c" ],
- mackerelDevices = [ "arm",
- "arm_icp_pit",
- "arm_icp_pic0",
- "pl011_uart" ],
- addLibraries = [ "elf", "cpio" ]
- },
- --
-- ARM Gem5 Cortex-A series ARMv7 core
--
cpuDriver {
target = "arm_gem5",
architectures = [ "armv7" ],
- assemblyFiles = [ "arch/arm_gem5/boot.S",
+ assemblyFiles = [ "arch/armv7/boot.S",
"arch/armv7/cp15.S",
"arch/armv7/exceptions.S" ],
- cFiles = [ "arch/arm/exec.c",
+ cFiles = [ "arch/armv7/plat_vexpress.c",
+ "arch/armv7/init.c",
+ "arch/arm/exec.c",
"arch/arm/misc.c",
"arch/arm/exn.c",
- "arch/arm/dispatch.c",
- "arch/arm/syscall.c",
- "arch/arm_gem5/init.c",
- "arch/armv7/gem5/integrator.c",
- "arch/arm_gem5/paging.c",
- "arch/arm/gem5/gem5_serial.c",
- "arch/arm/pl011_uart.c",
- "arch/arm_gem5/startup_arch.c",
+ "arch/arm/dispatch.c",
+ "arch/armv7/syscall.c",
+ "arch/arm/pl011.c",
+ "arch/arm/sp804.c",
+ "arch/armv7/startup_arch.c",
"arch/arm/gic.c",
+ "arch/armv7/a9_scu.c",
"arch/armv7/kludges.c",
"arch/armv7/paging.c",
"arch/arm/irq.c",
- "arch/armv7/gem5/start_aps.c",
"arch/arm/multiboot.c",
"arch/arm/kputchar.c" ],
mackerelDevices = [ "arm",
"pl130_gic",
"sp804_pit",
"cortex_a9_pit",
- "a9scu" ],
+ "cortex_a9_scu" ],
addLibraries = [ "elf", "cpio" ]
},
--
"arch/armv8/gem5/paging_gem5.c",
"arch/armv8/gem5/platform.c",
"arch/armv8/syscall.c",
- "arch/arm/gem5/gem5_serial.c",
"arch/arm/gem5/start_aps.c",
- "arch/arm/pl011_uart.c",
+ "arch/arm/pl011.c",
"arch/arm/gic.c",
"arch/arm/irq.c",
"arch/arm/multiboot.c",
"pl130_gic",
"sp804_pit",
"cortex_a9_pit",
- "a9scu" ],
+ "cortex_a9_scu" ],
addLibraries = [ "elf", "cpio" ]
},
--
- -- Intel ixp2800 XScale core
- --
- cpuDriver {
- target = "ixp2800",
- architectures = [ "xscale" ],
- assemblyFiles = [ "arch/xscale/boot.S",
- "arch/armv5/exceptions.S" ],
- cFiles = [ "arch/arm/exn.c",
- "arch/arm/exec.c",
- "arch/arm/misc.c",
- "arch/arm/dispatch.c",
- "arch/armv5/phys_mmap.c",
- "arch/arm/syscall.c",
- -- according to the Xscale documentation, the MMU is a
- -- standard ARMv5 design, so we should be able to use
- -- the armv5 cp15 code. -SG, 8/1/13
- "arch/armv5/cp15.c",
- "arch/armv5/init.c",
- "arch/armv5/kludges.c",
- "arch/armv5/startup_arch.c",
- "arch/xscale/ixp2800_integrator.c",
- "arch/xscale/ixp2800_uart.c",
- "arch/xscale/ixp2800_paging.c",
- "arch/arm/kputchar.c" ],
- mackerelDevices = [ "arm",
- "ixp2800_icp_pit",
- "ixp2800_icp_pic0",
- "ixp2800_uart" ],
- addLibraries = [ "elf", "cpio" ]
- },
- --
-- TI OMAP44xx-series dual-core Cortex-A9 SoC
--
cpuDriver {
target = "omap44xx",
architectures = [ "armv7" ],
- assemblyFiles = [ "arch/omap44xx/boot.S",
+ assemblyFiles = [ "arch/armv7/boot.S",
"arch/armv7/cp15.S",
"arch/armv7/exceptions.S" ],
cFiles = [ "arch/arm/exec.c",
- "arch/arm/misc.c",
- "arch/arm/exn.c",
"arch/arm/dispatch.c",
- "arch/arm/syscall.c",
+ "arch/arm/exn.c",
"arch/arm/gic.c",
- "arch/armv7/kludges.c",
- "arch/armv7/paging.c",
"arch/arm/irq.c",
- "arch/omap44xx/init.c",
- "arch/omap44xx/omap.c",
- "arch/omap44xx/paging.c",
- "arch/omap44xx/startup_arch.c",
- "arch/omap44xx/omap_uart.c",
- "arch/omap44xx/start_aps.c",
- "arch/omap44xx/spinlock.c",
+ "arch/arm/kputchar.c",
+ "arch/arm/misc.c",
"arch/arm/multiboot.c",
- "arch/arm/kputchar.c"],
+ "arch/arm/omap_uart.c",
+ "arch/armv7/syscall.c",
+ "arch/armv7/init.c",
+ "arch/armv7/a9_gt.c",
+ "arch/armv7/a9_scu.c",
+ "arch/armv7/kludges.c",
+ -- "arch/armv7/omap44xx_spinlock.c",
+ "arch/armv7/paging.c",
+ "arch/armv7/plat_omap44xx.c",
+ "arch/armv7/startup_arch.c"],
mackerelDevices = [ "arm",
"arm_icp_pit",
"pl130_gic",
"sp804_pit",
"cortex_a9_pit",
"cortex_a9_gt",
- "a9scu",
+ "cortex_a9_scu",
"omap/omap_uart",
"omap/omap44xx_id",
"omap/omap44xx_emif",
"omap/omap44xx_ckgen_prm",
"omap/omap44xx_l4per_cm2",
"omap/omap44xx_l3init_cm2",
+ "omap/omap44xx_cortexa9_wugen",
"omap/omap44xx_spinlock",
"omap/omap44xx_mmu",
"omap/omap44xx_gpio"],
addLibraries = [ "elf", "cpio" ]
},
- --
- -- TI OMAP44xx-series dual-core Cortex-M3 Coprocessor,
- -- Was used to run a heterogenous system on the pandaboard; no longer supported
- --
-
- cpuDriver {
- target = "omap44xx",
- architectures = [ "armv7-m" ],
- assemblyFiles = [ "arch/armv7-m/boot.S",
- "arch/armv7-m/exceptions.S" ],
- cFiles = [
- "arch/arm/misc.c",
- "arch/arm/syscall.c",
- "arch/arm/dispatch.c",
- "arch/armv7/kludges.c",
- "arch/armv7-m/exec.c",
- "arch/armv7-m/exn.c",
- "arch/armv7-m/init.c",
- "arch/armv7-m/omap.c",
- "arch/armv7-m/paging.c",
- "arch/omap44xx/startup_arch.c",
- "arch/omap44xx/omap_uart.c",
--- "arch/omap44xx/start_aps.c",
- "arch/arm/kputchar.c",
- "arch/arm/multiboot.c",
- "arch/omap44xx/spinlock.c"
- ],
- mackerelDevices = [ "arm",
- "omap/omap44xx_cortex_m3_nvic",
- "omap/omap_uart",
- "omap/omap44xx_id",
- "omap/omap44xx_emif",
- "omap/omap44xx_gpio",
- "omap/omap44xx_mmu",
- "omap/omap44xx_spinlock"],
- addLibraries = [ "elf", "cpio" ]
- },
--
-- Applied Micro APM88xxxx series SoC,
cp15_invalidate_i_and_d_caches();
__asm volatile(
-#ifndef __ARM_ARCH_5__
"clrex\n\t"
-#endif
// lr = r14, used as tmp register.
// Load cpsr into lr and move regs to next entry (postindex op)
// LDR = read word from memory
// Switch to system mode with interrupts enabled. -- OLD
// Switch to priviledged mode with interrupts enabled.
__asm volatile(
-#if defined(__ARM_ARCH_5__)
- //XXX: qemu 0.14 chokes on ARM_MODE_PRIV?! -SG
"mov r0, #" XTR(ARM_MODE_SYS) " \n\t"
-#else
- "mov r0, #" XTR(ARM_MODE_PRIV) " \n\t"
-#endif
"msr cpsr_c, r0 \n\t"
"0: \n\t"
-#if defined(__ARM_ARCH_6K__)
- "wfe \n\t"
-#elif defined(__ARM_ARCH_5TEJ__)
- "mcr p15, 0, r0, c7, c10, 4 \n\t"
-#elif defined(__ARM_ARCH_5TE__)
- // XXX: Need to change for Netronome?
- "mcr p15, 0, r0, c7, c10, 4 \n\t"
-#elif defined(__ARM_ARCH_7A__)
"wfi \n\t"
-#else
- // If no WFI functionality exists on system, just
- // spinning here is okay.
-#error "Unknown platform for wait_for_interrupt"
-#endif //
"b 0b \n\t" ::: "r0");
panic("wfi returned");
#include <stdio.h>
#include <wakeup.h>
#include <irq.h>
+#include <gic.h>
void handle_user_page_fault(lvaddr_t fault_address,
arch_registers_state_t* save_area)
void handle_irq(arch_registers_state_t* save_area, uintptr_t fault_pc)
{
uint32_t irq = 0;
-/* XXX - not revision-independent. */
-#if defined(__ARM_ARCH_7A__)
irq = gic_get_active_irq();
-#else
- // this is for ARMv5, -SG
- irq = pic_get_active_irq();
-#endif
-/* XXX - not 64-bit clean */
debug(SUBSYS_DISPATCH, "IRQ %"PRIu32" while %s\n", irq,
dcb_current ? (dcb_current->disabled ? "disabled": "enabled") : "in kernel");
// we just acknowledge it here
else if(irq == 1)
{
-/* XXX - not revision-independent. */
-#if defined(__ARM_ARCH_7A__)
gic_ack_irq(irq);
-#else
- // this is for ARMv5, -SG
- pic_ack_irq(irq);
-#endif
dispatch(schedule());
}
else {
-/* XXX - not revision-independent. */
-#if defined(__ARM_ARCH_7A__)
gic_ack_irq(irq);
send_user_interrupt(irq);
panic("Unhandled IRQ %"PRIu32"\n", irq);
-#else
- // SK: No support for user-level interrupts on ARMv5 and XScale
- panic("Unhandled IRQ %"PRIu32". User-level IRQs only supported on ARMv7!\n", irq);
-#endif
}
}
+++ /dev/null
-/**
- * \file
- * \brief ARM GEM5 kernel-level serial driver. Implements the
- * interface in /kernel/include/serial.h
- */
-/*
- * Copyright (c) 2007-2012 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, CAB F.78, Universitaestr. 6, CH-8092 Zurich.
- * Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <paging_kernel_arch.h>
-#include <serial.h>
-#include <dev/pl011_uart_dev.h>
-#include <arch/arm/pl011_uart.h>
-
-#define NUM_PORTS 2
-unsigned serial_console_port = 0;
-unsigned serial_debug_port = 0;
-const unsigned serial_num_physical_ports = NUM_PORTS;
-
-
-#define UART0_VBASE 0x1c090000
-#define UART0_SECTION_OFFSET 0x90000
-
-#define UART_DEVICE_BYTES 0x4c
-#define UART_MAPPING_DIFF 0x1000
-
-//static pl011_uart_t ports[NUM_PORTS];
-pl011_uart_t ports[NUM_PORTS];
-
-/*
- * Initialize a serial port
- */
-errval_t serial_init(unsigned port, bool hwinit)
-{
- if (port < NUM_PORTS) {
- lvaddr_t base = paging_map_device(UART0_VBASE + port*UART_MAPPING_DIFF,
- UART_DEVICE_BYTES);
- if (hwinit) {
- pl011_uart_init(&ports[port],
- base + UART0_SECTION_OFFSET + port*UART_MAPPING_DIFF);
- }
- return SYS_ERR_OK;
- } else {
- return SYS_ERR_SERIAL_PORT_INVALID;
- }
-}
-
-errval_t serial_early_init(unsigned port)
-{
- if (port < NUM_PORTS) {
- assert(ports[port].base == 0);
- pl011_uart_init(&ports[port], UART0_VBASE + port*UART_MAPPING_DIFF);
- return SYS_ERR_OK;
- } else {
- return SYS_ERR_SERIAL_PORT_INVALID;
- }
-}
-
-void serial_putchar(unsigned port, char c)
-{
- assert(port < NUM_PORTS);
- assert(ports[port].base != 0);
- pl011_putchar(&ports[port], c);
-};
-
-char serial_getchar(unsigned port)
-{
- assert(port < NUM_PORTS);
- assert(ports[port].base != 0);
- return pl011_getchar(&ports[port]);
-};
+++ /dev/null
-/**
- * \file
- * \brief Start the application processors
- *
- * This file sends all needed IPIs to the other cores to start them.
- */
-
-/*
- * Copyright (c) 2007, 2008, 2010, ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <stdio.h>
-#include <string.h>
-#include <arm_hal.h>
-#include <start_aps.h>
-
-#define STARTUP_TIMEOUT 0xffffff
-
-#pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
-
-/**
- * \brief Boot an arm app core
- *
- * \param core_id APIC ID of the core to try booting
- * \param entry Entry address for new kernel in the destination
- * architecture's lvaddr_t
- *
- * \returns Zero on successful boot, non-zero (error code) on failure
- */
-int start_aps_arm_start(coreid_t core_id, genvaddr_t entry)
-{
- panic("NYI");
-#if 0
- //write entry address of new kernel to SYSFLAG reg
- write_sysflags_reg(entry);
-
- //raise SWI to signal app core to start
- gic_raise_softirq((1 << core_id), 1);
-#endif
-
- return 0;
-}
#include <kernel.h>
#include <dev/pl130_gic_dev.h>
-#include <arm_hal.h>
#include <arch/arm/gic.h>
+#include <arm_hal.h>
+#include <platform.h>
+#include <paging_kernel_arch.h>
static pl130_gic_t gic;
static uint32_t it_num_lines;
static uint8_t cpu_number;
static uint8_t sec_extn_implemented;
+#define MSG(format, ...) printk( LOG_NOTE, "GIC: "format, ## __VA_ARGS__ )
+
enum IrqType {
IrqType_SGI,
IrqType_PPI,
IrqType_SPI
};
+#define DIST_SIZE 0x1000
+#define CPU_SIZE 0x1000
+
/**
* \brief Returns the IRQ type based on the interrupt ID
*
*/
void gic_init(void)
{
- // this function is implemented in platform-specific code
- gic_map_and_init(&gic);
+ lvaddr_t gic_dist_base = paging_map_device( platform_get_distributor_address(), DIST_SIZE );
+ lvaddr_t gic_cpu_base = paging_map_device( platform_get_gic_cpu_address(), CPU_SIZE );
+ pl130_gic_initialize(&gic, (mackerel_addr_t)gic_dist_base, (mackerel_addr_t)gic_cpu_base );
// read GIC configuration
gic_config = pl130_gic_ICDICTR_rd(&gic);
uint32_t it_num_lines_tmp = pl130_gic_ICDICTR_it_lines_num_extract(gic_config);
it_num_lines = 32*(it_num_lines_tmp + 1);
- printf("GIC: %d interrupt lines detected\n", it_num_lines_tmp);
+ MSG("%d interrupt lines detected\n", it_num_lines_tmp);
cpu_number = pl130_gic_ICDICTR_cpu_number_extract(gic_config);
sec_extn_implemented = pl130_gic_ICDICTR_TZ_extract(gic_config);
// Distributor:
// enable interrupt forwarding from distributor to cpu interface
pl130_gic_ICDDCR_enable_wrf(&gic, 0x1);
- printf("gic_init: done\n");
+ MSG("gic_init done\n");
}
void __attribute__((noreturn)) gic_disable_all_irqs(void)
uint32_t bit_mask = (1U << (int_id % 32));
uint32_t regval;
- printf("gic_enable_interrupt for id=0x%"PRIx32", "
+ MSG("gic_enable_interrupt for id=0x%"PRIx32", "
"offset=0x%"PRIx32", index=0x%"PRIx32"\n",
int_id, bit_mask, ind);
// Set the Interrupt Set Enable register to enable the interupt
// See ARM GIC TRM
if (irq_type == IrqType_SGI) {
- printf("Unhandled SGI IRQ %d\n", int_id);
+ MSG("unhandled SGI IRQ %d\n", int_id);
return; // Do nothing for SGI interrupts
}
#include <syscall.h>
#include <arch/arm/syscall_arm.h>
#include <kcb.h>
-
-#define GIC_IRQ_PRIO_LOWEST (0xF)
-#define GIC_IRQ_CPU_TRG_ALL (0x3) // For two cores on the PandaBoard
-#define GIC_IRQ_CPU_TRG_BSP (0x1)
-#define GIC_IRQ_EDGE_TRIGGERED (0x1)
-#define GIC_IRQ_LEVEL_SENSITIVE (0x0)
-#define GIC_IRQ_1_TO_N (0x1)
-#define GIC_IRQ_N_TO_N (0x0)
+#include <gic.h>
/**
* \brief User-space IRQ dispatch table.
#include <serial.h>
#include <kputchar.h>
#include <global.h>
-
-#include <spinlock.h>
+#include <barrelfish_kpi/spinlocks_arch.h>
#define KPBUFSZ 256
static char kputbuf[KPBUFSZ];
static void kflush(void)
{
- for(int i=0; i<kcount; i++)
+ for(int i=0; i<kcount; i++) {
serial_console_putchar(kputbuf[i]);
+ }
kcount = 0;
}
void kprintf_begin(void)
{
- spinlock_acquire(PRINTF_LOCK);
+ spinlock_acquire(&global->locks.print);
kcount = 0;
}
int kputchar(int c)
{
kputbuf[kcount++] = c;
- if (kcount == KPBUFSZ || c == '\n')
+ if (kcount == KPBUFSZ || c == '\n') {
kflush();
+ }
return c;
}
void kprintf_end(void)
{
kflush();
- spinlock_release(PRINTF_LOCK);
+ spinlock_release(&global->locks.print);
}
// End
/**
* \file
- * \brief Kernel serial driver for the OMAP44xx UARTs. Implements the
- * interface found in /kernel/include/serial.h
+ * \brief Kernel serial driver for the OMAP44xx UARTs.
*/
/*
- * Copyright (c) 2012, ETH Zurich.
+ * Copyright (c) 2012-2015, ETH Zurich.
* All rights reserved.
*
* This file is distributed under the terms in the attached LICENSE file.
* ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
*/
+#include <omap_uart.h>
+#include <dev/omap/omap_uart_dev.h>
#include <kernel.h>
#include <arm.h>
#include <paging_kernel_arch.h>
-#include <serial.h>
-#include <dev/omap/omap_uart_dev.h>
-#include <omap44xx_map.h>
-
//
// Serial console and debugger interfaces
//
-#define NUM_PORTS 4
-unsigned int serial_console_port = 2;
-unsigned int serial_debug_port = 2;
-unsigned const int serial_num_physical_ports = NUM_PORTS;
-
+#define NUM_PORTS 8
static omap_uart_t ports[NUM_PORTS];
+static lpaddr_t port_addrs[NUM_PORTS];
+static size_t port_sizes[NUM_PORTS];
+static bool port_inited[NUM_PORTS];
-static lpaddr_t uart_base[NUM_PORTS] = {
- OMAP44XX_MAP_L4_PER_UART1,
- OMAP44XX_MAP_L4_PER_UART2,
- OMAP44XX_MAP_L4_PER_UART3,
- OMAP44XX_MAP_L4_PER_UART4
-};
+static void omap_uart_hw_init(omap_uart_t *uart);
-static size_t uart_size[NUM_PORTS] = {
- OMAP44XX_MAP_L4_PER_UART1_SIZE,
- OMAP44XX_MAP_L4_PER_UART2_SIZE,
- OMAP44XX_MAP_L4_PER_UART3_SIZE,
- OMAP44XX_MAP_L4_PER_UART4_SIZE
-};
+#define MSG(port, format, ...) printk( LOG_NOTE, "OMAP serial[%d]: "format, port, ## __VA_ARGS__ )
/*
- * Initialzie OMAP UART
- * UART TRM 23.3
+ * Initialize UARTs before the MMU is on.
+ */
+void omap_uart_early_init(unsigned port, lpaddr_t base, size_t size)
+{
+ assert(port < NUM_PORTS);
+ // Bug to call twice on a port
+ assert(ports[port].base == 0);
+ port_sizes[port] = size;
+ port_addrs[port] = base;
+ omap_uart_initialize(&ports[port], (mackerel_addr_t) base);
+ omap_uart_hw_init(&ports[port]);
+ port_inited[port] = true;
+}
+
+/*
+ * Re-initialize UARTs after the MMU is on.
*/
-static void omap_uart_init(omap_uart_t *uart, lvaddr_t base)
+void omap_uart_init(unsigned port, bool initialize_hw)
{
- omap_uart_initialize(uart, (mackerel_addr_t) base);
+ assert( port < NUM_PORTS );
+ // Ensure port has already been initialized early
+ assert( port_sizes[port] != 0 );
+ assert( port_addrs[port] != 0 );
+
+ lvaddr_t base = paging_map_device( port_addrs[port], port_sizes[port] );
+ MSG(port, "base = 0x%"PRIxLVADDR"\n", base);
+ omap_uart_initialize(&ports[port], (mackerel_addr_t) base);
+ if (initialize_hw && !port_inited[port]) {
+ omap_uart_hw_init(&ports[port]);
+ port_inited[port] = true;
+ }
+ MSG(port,"done.\n");
+}
+/*
+ * Initialzie OMAP UART hardware
+ * UART TRM 23.3
+ */
+static void omap_uart_hw_init(omap_uart_t *uart)
+{
// do soft reset
omap_uart_SYSC_softreset_wrf(uart, 0x1);
while (!omap_uart_SYSS_resetdone_rdf(uart)); // poll for reset completion
omap_uart_MDR1_mode_select_wrf(uart, 0x0);
}
-errval_t serial_init(unsigned port, bool initialize_hw)
-{
- static bool uart_initialized[NUM_PORTS];
-
- if (port >= NUM_PORTS) {
- return SYS_ERR_SERIAL_PORT_INVALID;
- }
-
- if (uart_initialized[port]) {
- printf("omap serial_init[%d]: already initialized; skipping.\n", port);
- return SYS_ERR_OK;
- }
-
- lvaddr_t base = paging_map_device(uart_base[port],uart_size[port]);
- // paging_map_device returns an address pointing to the beginning of
- // a section, need to add the offset for within the section again
- uint32_t offset = (uart_base[port] & ARM_L1_SECTION_MASK);
- printf("omap serial_init[%d]: base = 0x%"PRIxLVADDR" 0x%"PRIxLVADDR"\n",
- port, base, base + offset);
- omap_uart_init(&ports[port], base + offset);
- uart_initialized[port] = true;
- printf("omap serial_init[%d]: done.\n", port);
- return SYS_ERR_OK;
-}
-
-errval_t serial_early_init(unsigned port)
-{
- if (port < NUM_PORTS) {
- // Bug to call twice on a port
- assert(ports[port].base == 0);
- omap_uart_init(&ports[port], uart_base[port]);
- return SYS_ERR_OK;
- } else {
- return SYS_ERR_SERIAL_PORT_INVALID;
- }
-}
-
/**
* \brief Prints a single character to a serial port.
*/
-void serial_putchar(unsigned port, char c)
+void omap_uart_putchar(unsigned port, char c)
{
assert(port <= NUM_PORTS);
omap_uart_t *uart = &ports[port];
* \brief Reads a single character from the default serial port.
* This function spins waiting for a character to arrive.
*/
-char serial_getchar(unsigned port)
+char omap_uart_getchar(unsigned port)
{
assert(port <= NUM_PORTS);
omap_uart_t *uart = &ports[port];
--- /dev/null
+/**
+ * \file
+ * \brief ARM pl011 UART kernel-level driver.
+ */
+
+/*
+ * Copyright (c) 2007, 2008, ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <dev/pl011_uart_dev.h>
+#include <arch/arm/pl011.h>
+#include <kernel.h>
+#include <paging_kernel_arch.h>
+#include <arch/arm/arm.h>
+
+
+// We can provide a maximum of 6 UARTs
+#define MAX_PORTS 6
+
+// How big is each PL011 in address space?
+#define UART_DEVICE_BYTES 0x4c
+
+static lpaddr_t addrs[ MAX_PORTS ];
+static pl011_uart_t uarts[ MAX_PORTS ];
+
+// Mask all interrupts in the IMSC register
+#define INTERRUPTS_MASK 0
+
+#define MSG(format, ...) printk( LOG_NOTE, "pl011: "format, ## __VA_ARGS__ )
+
+
+/**
+ * \brief Configure the serial interface, from a caller that knows
+ * that this is a bunch of PL011s, and furthermore where they are in
+ * the physical address space.
+ */
+void pl011_configure(unsigned n, lpaddr_t addr)
+{
+ assert( n < MAX_PORTS );
+ addrs[n] = addr;
+ pl011_uart_initialize(&uarts[n], (mackerel_addr_t)(addrs[n]));
+}
+
+/*
+ * \brief Initialize a serial port. The MMU is turned on.
+ */
+void pl011_init(unsigned port, bool hwinit)
+{
+ assert( port < MAX_PORTS );
+ pl011_uart_t *u = &uarts[port];
+
+ // Map the UART hardware into kernel virtual memory
+ lvaddr_t base = paging_map_device( addrs[port], UART_DEVICE_BYTES );
+
+ // Don't look down...
+ MSG("base is 0x%"PRIxLVADDR"\n", (uint32_t)base);
+
+ // [Re]initialize the Mackerel state for the UART
+ pl011_uart_initialize(u, (mackerel_addr_t) base);
+
+ if (hwinit) {
+ // Mask all interrupts: set all bits to zero
+ pl011_uart_IMSC_rawwr(u, INTERRUPTS_MASK);
+
+ // Configure port to 38400 baud, 8 data, no parity, 1 stop (8-N-1)
+ //
+ // (This is a mild scam as system is running in QEMU)
+ //
+ // Note baud rate changes not committed in h/w until lcr_h
+ // written.
+ pl011_uart_IBRD_divint_wrf(u, 0xc); // Assuming UARTCLK is 7.3728MHz
+ pl011_uart_FBRD_divfrac_wrf(u, 0);
+
+ // Set 8 bits, no parity
+ pl011_uart_LCR_H_t lcr = (pl011_uart_LCR_H_t)0;
+ pl011_uart_LCR_H_fen_insert(lcr, 1);
+ pl011_uart_LCR_H_wlen_insert(lcr, pl011_uart_bits8);
+ pl011_uart_LCR_H_wr(u, lcr);
+ }
+ MSG("initialized at 0x%"PRIxLVADDR"\n", base);
+}
+
+/*
+ * \brief Put a character to the port
+ */
+void pl011_putchar(unsigned port, char c)
+{
+ assert(port < MAX_PORTS );
+ pl011_uart_t *u = &uarts[port];
+ assert(u->base != 0);
+
+ while (pl011_uart_FR_txff_rdf(u) == 1)
+ ;
+ pl011_uart_DR_rawwr(u, c);
+ // pl011_uart_DR_t dr;
+ // dr = (pl011_uart_DR_t)0;
+ // pl011_uart_DR_data_insert(dr, (uint8_t)c);
+};
+
+
+/*
+ * \brief Read a character from a port
+ */
+char pl011_getchar(unsigned port)
+{
+ assert(port < MAX_PORTS );
+ pl011_uart_t *u = &uarts[port];
+ assert(u->base != 0);
+
+ while (pl011_uart_FR_rxfe_rdf(u) == 1)
+ ;
+ return (char) pl011_uart_DR_data_rdf(u);
+};
+++ /dev/null
-/**
- * \file
- * \brief ARM pl011 UART kernel-level driver.
- */
-
-/*
- * Copyright (c) 2007, 2008, ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <arch/arm/arm.h>
-
-#include <dev/pl011_uart_dev.h>
-#include <arch/arm/pl011_uart.h>
-
-#define INTERRUPTS_MASK 0
-
-void pl011_uart_init(pl011_uart_t *uart, lvaddr_t base)
-{
- pl011_uart_LCR_H_t lcr = {
- .brk = 0, .pen = 0, .eps = 0, .stp2 = 0, .fen = 1,
- .wlen = pl011_uart_bits8, .sps = 0
- };
-
- pl011_uart_initialize(uart, (mackerel_addr_t) base);
-
- // Mask all interrupts
- pl011_uart_IMSC_wr_raw(uart, INTERRUPTS_MASK);
-
- // Configure port to 38400 baud, 8 data, no parity, 1 stop (8-N-1)
- //
- // (This is a mild scam as system is running in QEMU)
- //
- // Note baud rate changes not committed in h/w until lcr_h written.
-
- pl011_uart_IBRD_wr_raw(uart, 0xc); // Assuming UARTCLK is 7.3728MHz
- pl011_uart_FBRD_wr_raw(uart, 0);
-
- pl011_uart_LCR_H_wr(uart, lcr);
-}
-
-/** \brief Prints a single character to the default serial port. */
-void pl011_putchar(pl011_uart_t *uart, char c)
-{
- pl011_uart_DR_un dr_un;
-
- while (pl011_uart_FR_rd(uart).txff == 1)
- ;
-
- dr_un.raw = 0;
- dr_un.val.data = (uint8_t)c;
- pl011_uart_DR_wr(uart, dr_un.val);
-}
-
-/** \brief Reads a single character from the default serial port.
- * This function spins waiting for a character to arrive.
- */
-char pl011_getchar(pl011_uart_t *uart)
-{
- while (pl011_uart_FR_rd(uart).rxfe == 1)
- ;
-
- return (char) pl011_uart_DR_rd(uart).data;
-}
--- /dev/null
+/**
+ * \file
+ * \brief SP804 ARM dual timer module driver for the arm_hal 'pit'
+ * interface.
+ */
+/*
+ * Copyright (c) 2015 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <dev/sp804_pit_dev.h>
+#include <sp804.h>
+#include <gic.h>
+#include <arm_hal.h>
+#include <paging_kernel_arch.h>
+
+
+/*
+ * Size of the SP804 device in memory
+ */
+#define PIT_SIZE 0x1000
+
+/*
+ * The timers themselves
+ */
+#define MAX_TIMERS 4
+struct pit {
+ lpaddr_t paddr;
+ uint32_t irq;
+ sp804_pit_t pit;
+};
+static struct pit pits[MAX_TIMERS/2];
+static size_t num_timers = 0;
+static uint32_t freq = 0;
+
+/**
+ * \brief Configure the timer chips.
+ *
+ * We expose the timers individually, and simply trust that the rest
+ * of the CPU driver knows that each pair of timers shares a single
+ * interrupt line. We also require that the MMU is turned on at this
+ * point.
+ *
+ * \param n the number of timers
+ * \param hz the clock frequency of the timers in Hertz
+ * \param addrs an array of n physical addresses of sp804 devices
+ * \param irqs an array of n irq numbers for the devices
+ */
+void sp804_configure(size_t n, uint32_t hz, const lpaddr_t addrs[], const uint32_t irqs[] )
+{
+ // assert( paging_mmu_enabled() );
+ assert( n*2 <= MAX_TIMERS );
+ num_timers = n;
+ freq = hz;
+ for( int i=0; i < n; i++ ) {
+ lvaddr_t pit_vaddr;
+ struct pit *p = &pits[i];
+ p->paddr = addrs[i];
+ p->irq = irqs[i];
+ pit_vaddr = paging_map_device( pits[i].paddr, PIT_SIZE );
+ sp804_pit_initialize(&p->pit, (mackerel_addr_t)pit_vaddr);
+ }
+}
+
+/**
+ * \brief Initialize a timer to run periodically
+ *
+ * \param timeslice the frequency of the desired tick in hertz.
+ * \param timer the number of the timer to program.
+ *
+ * Note that each sp804 has two timers, and so this will program the
+ * timer <timer%2> of sp804 <timer/2>.
+ */
+void pit_init(uint32_t timeslice, size_t timer)
+{
+ // We must have called sp804_configure by this point. If we
+ // haven't, num_timers will be 0 and this assertion will fail.
+ assert(timer < num_timers);
+ struct pit *p = &pits[timer/2];
+ sp804_pit_t *sp = &p->pit;
+ // XXX Why this 1000 factor?
+ uint32_t loadval = timeslice * freq / 1000;
+
+ // Program the timer
+ if ( (timer % 2) == 0 ) {
+ sp804_pit_Timer1Load_wr(sp, loadval);
+ sp804_pit_Timer1Control_one_shot_wrf(sp, 0);
+ sp804_pit_Timer1Control_timer_size_wrf(sp, sp804_pit_size_32bit);
+ sp804_pit_Timer1Control_timer_pre_wrf(sp, sp804_pit_prescale0);
+ sp804_pit_Timer1Control_int_enable_wrf(sp, 0);
+ sp804_pit_Timer1Control_timer_mode_wrf(sp, sp804_pit_periodic);
+ sp804_pit_Timer1Control_timer_en_wrf(sp, 0);
+ } else {
+ sp804_pit_Timer2Load_wr(sp, loadval);
+ sp804_pit_Timer2Control_one_shot_wrf(sp, 0);
+ sp804_pit_Timer2Control_timer_size_wrf(sp, sp804_pit_size_32bit);
+ sp804_pit_Timer2Control_timer_pre_wrf(sp, sp804_pit_prescale0);
+ sp804_pit_Timer2Control_int_enable_wrf(sp, 0);
+ sp804_pit_Timer2Control_timer_mode_wrf(sp, sp804_pit_periodic);
+ sp804_pit_Timer2Control_timer_en_wrf(sp, 0);
+ }
+
+ // Enable PIT interrupt
+ gic_enable_interrupt(p->irq, 0x1, 0xf, 0x1, 0);
+}
+
+/**
+ * \brief Start a timer running after configuring it.
+ *
+ * \param timer a timer number.
+ *
+ * This enables interrupts and starts the timer running.
+ */
+void pit_start(size_t timer)
+{
+ assert(timer < num_timers);
+ sp804_pit_t *sp = &pits[timer/2].pit;
+
+ if ( (timer % 2) == 0 ) {
+ sp804_pit_Timer1Control_int_enable_wrf(sp, 1);
+ sp804_pit_Timer1Control_timer_en_wrf(sp, 1);
+ } else {
+ sp804_pit_Timer2Control_int_enable_wrf(sp, 1);
+ sp804_pit_Timer2Control_timer_en_wrf(sp, 1);
+ }
+}
+
+/**
+ * \brief Handle an interrupt
+ *
+ * \param irq an IRQ number of the interrupt
+ *
+ * Currently, clears the interrupt condition on both timers on the
+ * relevant SP804.
+ */
+bool pit_handle_irq(uint32_t irq)
+{
+ // XXX could be more efficient
+ for( int i = 0; i < num_timers / 2; i++ ) {
+ if (pits[i].irq == irq) {
+ sp804_pit_Timer1IntClr_wr(&pits[i].pit, ~0ul);
+ sp804_pit_Timer2IntClr_wr(&pits[i].pit, ~0ul);
+ gic_ack_irq(irq);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/**
+ * \brief Mask the interrupts from a given timer.
+ *
+ * \param masked whether to set or clear the mask.
+ * \param timer the timer whose interrupt to clear
+ *
+ * Currently, clears the interrupt condition on both timers on the
+ * relevant SP804.
+ */
+void pit_mask_irq(bool masked, size_t timer)
+{
+ assert(timer < num_timers);
+ struct pit *p = &pits[timer/2];
+ sp804_pit_t *sp = &p->pit;
+ if (masked) {
+ sp804_pit_Timer1Control_int_enable_wrf(sp, 0);
+ }
+ else {
+ sp804_pit_Timer1Control_int_enable_wrf(sp, 1);
+ }
+ if (masked) {
+ // Clear interrupt if pending.
+ pit_handle_irq(p->irq);
+ }
+}
+++ /dev/null
-/**
- * \file
- * \brief Bootstrap the kernel.
- */
-/*
- * Copyright (c) 2009 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#ifndef __ASSEMBLER__
-#define __ASSEMBLER__ 1
-#endif
-
-#include <barrelfish_kpi/flags_arch.h> // ARM_MODE_MASK
-#include <offsets.h> // BOOT_STACK_PHYS
-
- .text
- .arm
-
- .globl start, halt, got_base
- .extern kernel_stack, glbl_core_data
-
- // Used to track phys memory allocator limit globally.
- alloc_top .req r11
-
-start:
- // On entry:
- //
- // MMU disabled
- // Caches in unknown state, but no lockdown
- // No TLB lockdown.
- // CPU is in a priviledged mode.
- //
- mrs r3, cpsr // Ensure in SYS mode
- bic r3, r3, #ARM_MODE_MASK
- orr r3, r3, #ARM_MODE_SYS
- msr cpsr_c, r3
-
- //init stack
- ldr sp, =kernel_stack
- add sp, sp, #KERNEL_STACK_SIZE
-
- ldr PIC_REGISTER, =got_base
-
- //prepare argument
- mov r0, r2
- b arch_init
- b halt
-
-
-/**
- * extern "C" void halt(void) __attribute__((noreturn))
- */
-halt:
- b .
-
-.ltorg
-
-got_base:
- .word // Initialized by linker
-
- .end
+++ /dev/null
-/*
- * Copyright (c) 2009 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <string.h>
-#include <init.h>
-#include <exceptions.h>
-#include <exec.h>
-#include <offsets.h>
-#include <paging_kernel_arch.h>
-#include <serial.h>
-#include <stdio.h>
-#include <arm_hal.h>
-#include <cpiobin.h>
-#include <getopt/getopt.h>
-#include <cp15.h>
-#include <spinlock.h>
-#include <elf/elf.h>
-#include <barrelfish_kpi/arm_core_data.h>
-
-#include <startup_arch.h>
-#include <kernel_multiboot.h>
-#include <global.h>
-#include <start_aps.h>
-#include <kcb.h>
-#include <coreboot.h>
-
-#define GEM5_RAM_SIZE (256UL*1024*1024)
-
-//
-// XXX Missing ARM HAL functionality - to be moved elsewhere
-//
-void spinlock_acquire(int locknumber) { return; }
-void spinlock_release(int locknumber) { return; }
-uint32_t gt_read_low(void) { return 0; }
-uint32_t gt_read_high(void) { return 0; }
-
-/// Round up n to the next multiple of size
-#define ROUND_UP(n, size) ((((n) + (size) - 1)) & (~((size) - 1)))
-
-/**
- * Used to store the address of global struct passed during boot across kernel
- * relocations.
- */
-//static uint32_t addr_global;
-
-/**
- * \brief Kernel stack.
- *
- * This is the one and only kernel stack for a kernel instance.
- */
-uintptr_t kernel_stack[KERNEL_STACK_SIZE/sizeof(uintptr_t)]
-__attribute__ ((aligned(8)));
-
-/**
- * Boot-up L1 page table for addresses up to 2GB (translated by TTBR0)
- */
-//XXX: We reserve double the space needed to be able to align the pagetable
-// to 16K after relocation
-static union arm_l1_entry boot_l1_low[2*ARM_L1_MAX_ENTRIES]
-__attribute__ ((aligned(ARM_L1_ALIGN)));
-static union arm_l1_entry * aligned_boot_l1_low;
-/**
- * Boot-up L1 page table for addresses >=2GB (translated by TTBR1)
- */
-//XXX: We reserve double the space needed to be able to align the pagetable
-// to 16K after relocation
-static union arm_l1_entry boot_l1_high[2*ARM_L1_MAX_ENTRIES]
-__attribute__ ((aligned(ARM_L1_ALIGN)));
-static union arm_l1_entry * aligned_boot_l1_high;
-
-//
-// ATAG boot header declarations
-//
-// See: http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html
-//
-
-static const uint32_t ATAG_NONE = 0;
-static const uint32_t ATAG_CORE = 0x54410001;
-static const uint32_t ATAG_MEM = 0x54410002;
-static const uint32_t ATAG_VIDEOTEXT = 0x54410003;
-static const uint32_t ATAG_RAMDISK = 0x54410004;
-static const uint32_t ATAG_INITRD2 = 0x54420005;
-static const uint32_t ATAG_SERIAL = 0x54410006;
-static const uint32_t ATAG_REVISION = 0x54410007;
-static const uint32_t ATAG_VIDEOLFB = 0x54410008;
-static const uint32_t ATAG_CMDLINE = 0x54410009;
-
-struct atag_header {
- uint32_t size; // Size of header plus payload in 32-bit words
- uint32_t tag; // Payload identifier
-};
-
-struct atag_core {
- uint32_t flags; // bit 0 = r/o
- uint32_t page_bytes;
- uint32_t root_device;
-};
-
-struct atag_mem {
- uint32_t bytes;
- uint32_t start;
-};
-
-struct atag_videotext {
- uint8_t width;
- uint8_t height;
- uint16_t video_page;
- uint8_t video_mode;
- uint8_t video_cols;
- uint16_t video_ega_bx;
- uint8_t video_lines;
- uint8_t video_isvga;
- uint16_t video_points;
-};
-
-struct atag_ramdisk {
- uint32_t flags; // Bit 0 = load, bit 1 = prompt
- uint32_t bytes; // Decompressed size
- uint32_t start; // Starting block of RAM disk image
-};
-
-struct atag_initrd2 {
- uint32_t start; // Physical start address
- uint32_t bytes; // Copmressed disk image in bytes
-};
-
-struct atag_serial {
- uint32_t low; // Lower order bits of board serial number
- uint32_t high; // Upper order bits of board serial number
-};
-
-struct atag_revision {
- uint32_t board_revision;
-};
-
-struct atag_videolfb
-{
- uint16_t lfb_width;
- uint16_t lfb_height;
- uint16_t lfb_depth;
- uint16_t lfb_linelength;
- uint32_t lfb_base;
- uint32_t lfb_size;
- uint8_t red_size;
- uint8_t red_pos;
- uint8_t green_size;
- uint8_t green_pos;
- uint8_t bluint_te_size;
- uint8_t bluint_te_pos;
- uint8_t rsvd_size;
- uint8_t rsvd_pos;
-};
-
-struct atag_cmdline
-{
- char cmdline[1];
-};
-
-struct atag {
- struct atag_header header;
- union {
- struct atag_core core;
- struct atag_mem mem;
- struct atag_videotext videotext;
- struct atag_ramdisk ramdisk;
- struct atag_initrd2 initrd2;
- struct atag_serial serial;
- struct atag_revision revision;
- struct atag_videolfb videolfb;
- struct atag_cmdline cmdline;
- } u;
-};
-
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#define CONSTRAIN(x, a, b) MIN(MAX(x, a), b)
-
-//
-// Kernel command line variables and binding options
-//
-
-static int timeslice = 5; //interval in ms in which the scheduler gets called
-
-static struct cmdarg cmdargs[] = {
- { "consolePort", ArgType_UInt, { .uinteger = &serial_console_port}},
- { "debugPort", ArgType_UInt, { .uinteger = &serial_debug_port}},
- { "loglevel", ArgType_Int, { .integer = &kernel_loglevel }},
- { "logmask", ArgType_Int, { .integer = &kernel_log_subsystem_mask }},
- { "timeslice", ArgType_Int, { .integer = ×lice }},
- {NULL, 0, {NULL}}
-};
-
-static inline void __attribute__ ((always_inline))
-relocate_stack(lvaddr_t offset)
-{
- __asm volatile (
- "add sp, sp, %[offset]\n\t" :: [offset] "r" (offset)
- );
-}
-
-static inline void __attribute__ ((always_inline))
-relocate_got_base(lvaddr_t offset)
-{
- __asm volatile (
- "add r10, r10, %[offset]\n\t" :: [offset] "r" (offset)
- );
-}
-
-#ifndef __gem5__
-static void enable_cycle_counter_user_access(void)
-{
- /* enable user-mode access to the performance counter*/
- __asm volatile ("mcr p15, 0, %0, C9, C14, 0\n\t" :: "r"(1));
-
- /* disable counter overflow interrupts (just in case)*/
- __asm volatile ("mcr p15, 0, %0, C9, C14, 2\n\t" :: "r"(0x8000000f));
-}
-#endif
-
-static void paging_init(void)
-{
- // configure system to use TTBR1 for VAs >= 2GB
- uint32_t ttbcr;
- ttbcr = cp15_read_ttbcr();
- ttbcr |= 1;
- cp15_write_ttbcr(ttbcr);
-
- // make sure pagetables are aligned to 16K
- aligned_boot_l1_low = (union arm_l1_entry *)ROUND_UP((uintptr_t)boot_l1_low, ARM_L1_ALIGN);
- aligned_boot_l1_high = (union arm_l1_entry *)ROUND_UP((uintptr_t)boot_l1_high, ARM_L1_ALIGN);
-
- lvaddr_t vbase = MEMORY_OFFSET, base = 0;
-
- for(size_t i=0; i < ARM_L1_MAX_ENTRIES/2; i++,
- base += ARM_L1_SECTION_BYTES, vbase += ARM_L1_SECTION_BYTES)
- {
- // create 1:1 mapping
- paging_map_kernel_section((uintptr_t)aligned_boot_l1_low, base, base);
-
- // Alias the same region at MEMORY_OFFSET
- paging_map_kernel_section((uintptr_t)aligned_boot_l1_high, vbase, base);
- }
-
- // Activate new page tables
- cp15_write_ttbr1((lpaddr_t)aligned_boot_l1_high);
- //cp15_write_ttbr0((lpaddr_t)&boot_l1_high[0]);
- cp15_write_ttbr0((lpaddr_t)aligned_boot_l1_low);
-}
-
-void kernel_startup_early(void)
-{
- const char *cmdline;
- assert(glbl_core_data != NULL);
- cmdline = MBADDR_ASSTRING(glbl_core_data->cmdline);
- parse_commandline(cmdline, cmdargs);
- timeslice = CONSTRAIN(timeslice, 1, 20);
-}
-
-/**
- * \brief Continue kernel initialization in kernel address space.
- *
- * This function resets paging to map out low memory and map in physical
- * address space, relocating all remaining data structures. It sets up exception handling,
- * initializes devices and enables interrupts. After that it
- * calls arm_kernel_startup(), which should not return (if it does, this function
- * halts the kernel).
- */
-static void __attribute__ ((noinline,noreturn)) text_init(void)
-{
- errval_t errval;
- // Relocate glbl_core_data to "memory"
- glbl_core_data = (struct arm_core_data *)
- local_phys_to_mem((lpaddr_t)glbl_core_data);
-
- // Relocate global to "memory"
- global = (struct global*)local_phys_to_mem((lpaddr_t)global);
-
- // Map-out low memory
- if(glbl_core_data->multiboot_flags & MULTIBOOT_INFO_FLAG_HAS_MMAP) {
- struct arm_coredata_mmap *mmap = (struct arm_coredata_mmap *)
- local_phys_to_mem(glbl_core_data->mmap_addr);
- paging_arm_reset(mmap->base_addr, mmap->length);
- } else {
- paging_arm_reset(PHYS_MEMORY_START, GEM5_RAM_SIZE);
- }
-
- exceptions_init();
-
- kernel_startup_early();
-
- //initialize console
- serial_console_init(true);
-
- // do not remove/change this printf: needed by regression harness
- printf("Barrelfish CPU driver starting on ARMv7 Board id 0x%08"PRIx32"\n", hal_get_board_id());
- printf("The address of paging_map_kernel_section is %p\n", paging_map_kernel_section);
-
- errval = serial_debug_init();
- if (err_is_fail(errval)) {
- printf("Failed to initialize debug port: %d", serial_debug_port);
- }
-
- my_core_id = hal_get_cpu_id();
-
- gic_init();
-
- if(hal_cpu_is_bsp()) {
- // init SCU if more than one core present
- if(scu_get_core_count() > 4) {
- panic("ARM SCU doesn't support more than 4 cores!");
- }
- if(scu_get_core_count() > 1) {
- scu_enable();
- }
- }
-
- pit_init(timeslice, 0);
- pit_init(timeslice, 1);
- tsc_init();
-
-#ifndef __gem5__
- enable_cycle_counter_user_access();
- reset_cycle_counter();
-#endif
-
- coreboot_set_spawn_handler(CPU_ARM7, start_aps_arm_start);
- arm_kernel_startup();
-}
-
-/**
- * Entry point called from boot.S for bootstrap processor.
- * if is_bsp == true, then pointer points to multiboot_info
- * else pointer points to a global struct
- */
-
-void arch_init(void *pointer)
-{
- void __attribute__ ((noreturn)) (*reloc_text_init)(void) =
- (void *)local_phys_to_mem((lpaddr_t)text_init);
-
- struct Elf32_Shdr *rela, *symtab;
- struct arm_coredata_elf *elf = NULL;
-
- serial_early_init(serial_console_port);
-
- if(hal_cpu_is_bsp()) {
- struct multiboot_info *mb = (struct multiboot_info *)pointer;
- elf = (struct arm_coredata_elf *)&mb->syms.elf;
- memset(glbl_core_data, 0, sizeof(struct arm_core_data));
- glbl_core_data->start_free_ram =
- ROUND_UP(max(multiboot_end_addr(mb), (uintptr_t)&kernel_final_byte),
- BASE_PAGE_SIZE);
-
- glbl_core_data->mods_addr = mb->mods_addr;
- glbl_core_data->mods_count = mb->mods_count;
- glbl_core_data->cmdline = mb->cmdline;
- glbl_core_data->mmap_length = mb->mmap_length;
- glbl_core_data->mmap_addr = mb->mmap_addr;
- glbl_core_data->multiboot_flags = mb->flags;
-
- // Construct the global structure
- memset(&global->locks, 0, sizeof(global->locks));
-
- } else {
- global = (struct global *)GLOBAL_VBASE;
- memset(&global->locks, 0, sizeof(global->locks));
- struct arm_core_data *core_data =
- (struct arm_core_data*)((lvaddr_t)&kernel_first_byte - BASE_PAGE_SIZE);
- glbl_core_data = core_data;
- glbl_core_data->cmdline = (lpaddr_t)&core_data->kernel_cmdline;
- my_core_id = core_data->dst_core_id;
- elf = &core_data->elf;
- }
-
- // XXX: print kernel address for debugging with gdb
- printf("Kernel starting at address 0x%"PRIxLVADDR"\n",
- local_phys_to_mem((uint32_t)&kernel_first_byte));
-
- // Find relocation section
- rela = elf32_find_section_header_type((struct Elf32_Shdr *)
- ((uintptr_t)elf->addr),
- elf->num, SHT_REL);
-
- if (rela == NULL) {
- panic("Kernel image does not include relocation section!");
- }
-
- // Find symtab section
- symtab = elf32_find_section_header_type((struct Elf32_Shdr *)(lpaddr_t)elf->addr,
- elf->num, SHT_DYNSYM);
-
- if (symtab == NULL) {
- panic("Kernel image does not include symbol table!");
- }
-
- paging_init();
-
- cp15_enable_mmu();
-
- // Relocate kernel image for top of memory
- elf32_relocate(MEMORY_OFFSET + (lvaddr_t)&kernel_first_byte,
- (lvaddr_t)&kernel_first_byte,
- (struct Elf32_Rel *)(rela->sh_addr - START_KERNEL_PHYS + &kernel_first_byte),
- rela->sh_size,
- (struct Elf32_Sym *)(symtab->sh_addr - START_KERNEL_PHYS + &kernel_first_byte),
- symtab->sh_size,
- START_KERNEL_PHYS, &kernel_first_byte);
- /*** Aliased kernel available now -- low memory still mapped ***/
-
- // Relocate stack to aliased location
- relocate_stack(MEMORY_OFFSET);
-
- //relocate got_base register to aliased location
- relocate_got_base(MEMORY_OFFSET);
-
- // Call aliased text_init() function and continue initialization
- reloc_text_init();
-}
+++ /dev/null
-/*
- * Copyright (c) 2009 - 2012 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <cp15.h>
-#include <paging_kernel_arch.h>
-#include <string.h>
-#include <exceptions.h>
-#include <arm_hal.h>
-#include <cap_predicates.h>
-#include <dispatch.h>
-
-/**
- * Kernel L1 page table
- */
-//XXX: We reserve double the space needed to be able to align the pagetable
-// to 16K after relocation
-static union arm_l1_entry kernel_l1_table[2*ARM_L1_MAX_ENTRIES]
-__attribute__((aligned(ARM_L1_ALIGN)));
-static union arm_l1_entry *aligned_kernel_l1_table;
-/**
- * Kernel L2 page table for first MB
- */
-//XXX: We reserve double the space needed to be able to align the pagetable
-// to 1K after relocation
-static union arm_l2_entry low_l2_table[2*ARM_L2_MAX_ENTRIES]
-__attribute__((aligned(ARM_L2_ALIGN)));
-static union arm_l2_entry *aligned_low_l2_table;
-
-// ------------------------------------------------------------------------
-// Utility declarations
-
-inline static uintptr_t paging_round_down(uintptr_t address, uintptr_t size)
-{
- return address & ~(size - 1);
-}
-
-inline static uintptr_t paging_round_up(uintptr_t address, uintptr_t size)
-{
- return (address + size - 1) & ~(size - 1);
-}
-
-inline static int aligned(uintptr_t address, uintptr_t bytes)
-{
- return (address & (bytes - 1)) == 0;
-}
-
-static void
-paging_write_l1_entry(uintptr_t ttbase, lvaddr_t va, union arm_l1_entry l1)
-{
- union arm_l1_entry *l1_table;
- if (ttbase == 0) {
- if(va < MEMORY_OFFSET)
- ttbase = cp15_read_ttbr0() + MEMORY_OFFSET;
- else
- ttbase = cp15_read_ttbr1() + MEMORY_OFFSET;
- }
- l1_table = (union arm_l1_entry *) ttbase;
- l1_table[ARM_L1_OFFSET(va)] = l1;
-}
-// ------------------------------------------------------------------------
-// Exported functions
-
-
-void paging_map_kernel_section(uintptr_t ttbase, lvaddr_t va, lpaddr_t pa)
-{
-
- union arm_l1_entry l1;
-
- l1.raw = 0;
- l1.section.type = L1_TYPE_SECTION_ENTRY;
- l1.section.bufferable = 1;
- l1.section.cacheable = 1;
- l1.section.ap10 = 1; // RW/NA
- l1.section.ap2 = 0;
- l1.section.base_address = pa >> 20u;
-
- paging_write_l1_entry(ttbase, va, l1);
-}
-
-void paging_map_memory(uintptr_t ttbase, lpaddr_t paddr, size_t bytes)
-{
- lpaddr_t pend = paging_round_up(paddr + bytes, BYTES_PER_SECTION);
- while (paddr < pend) {
- paging_map_kernel_section(ttbase, paddr + MEMORY_OFFSET, paddr);
- paddr += BYTES_PER_SECTION;
- }
-}
-
-
-static void
-paging_map_device_section(uintptr_t ttbase, lvaddr_t va, lpaddr_t pa)
-{
- union arm_l1_entry l1;
-
- l1.raw = 0;
- l1.section.type = L1_TYPE_SECTION_ENTRY;
- l1.section.bufferable = 0;
- l1.section.cacheable = 0;
- l1.section.ap10 = 1; // RW/NA
- l1.section.ap2 = 0;
- l1.section.base_address = pa >> 20u;
-
- paging_write_l1_entry(ttbase, va, l1);
-}
-
-lvaddr_t paging_map_device(lpaddr_t device_base, size_t device_bytes)
-{
- // HACK to put device in high memory.
- // Should likely track these allocations.
- static lvaddr_t dev_alloc = DEVICE_OFFSET;
- assert(device_bytes <= BYTES_PER_SECTION);
- dev_alloc -= BYTES_PER_SECTION;
-
- paging_map_device_section((uintptr_t)aligned_kernel_l1_table, dev_alloc, device_base);
-
- return dev_alloc;
-}
-
-/**
- * \brief Reset kernel paging.
- *
- * This function resets the page maps for kernel and memory-space. It clears out
- * all other mappings. Use this only at system bootup!
- */
-void paging_arm_reset(lpaddr_t paddr, size_t bytes)
-{
- // make sure kernel pagetable is aligned to 16K after relocation
- aligned_kernel_l1_table = (union arm_l1_entry *)ROUND_UP((uintptr_t)kernel_l1_table, ARM_L1_ALIGN);
-
- // make sure low l2 pagetable is aligned to 1K after relocation
- aligned_low_l2_table = (union arm_l2_entry *)ROUND_UP((uintptr_t)low_l2_table, ARM_L2_ALIGN);
-
- // Re-map physical memory
- paging_map_memory((uintptr_t)aligned_kernel_l1_table, paddr, bytes);
-
- // map first MB at granularity of 4K pages
- uint32_t l2_flags = ARM_L2_SMALL_USR_NONE | ARM_L2_SMALL_CACHEABLE | ARM_L2_SMALL_BUFFERABLE;
- paging_map_user_pages_l1((uintptr_t)aligned_kernel_l1_table, MEMORY_OFFSET,
- mem_to_local_phys((uintptr_t)aligned_low_l2_table));
- for(lpaddr_t pa=0; pa < ARM_L1_SECTION_BYTES; pa += BYTES_PER_PAGE)
- {
- lvaddr_t va = pa + MEMORY_OFFSET;
- paging_set_l2_entry((uintptr_t *)&aligned_low_l2_table[ARM_L2_OFFSET(va)], pa, l2_flags);
- }
-
- // map high-mem relocated exception vector to corresponding page in low MB
- // core 0: 0xffff0000 -> 0x80000
- // core 1: 0xffff0000 -> 0x81000
- // ...
- paging_map_user_pages_l1((uintptr_t)aligned_kernel_l1_table, ETABLE_ADDR,
- mem_to_local_phys((uintptr_t)aligned_low_l2_table));
- int core_id = hal_get_cpu_id();
- lpaddr_t addr = ETABLE_PHYS_BASE + core_id * BASE_PAGE_SIZE;
- paging_set_l2_entry((uintptr_t *)&aligned_low_l2_table[ARM_L2_OFFSET(ETABLE_ADDR)], addr, l2_flags);
-
- cp15_write_ttbr1(mem_to_local_phys((uintptr_t)aligned_kernel_l1_table));
-
- cp15_invalidate_tlb();
-}
-
-
-void paging_make_good(lvaddr_t new_table_base, size_t new_table_bytes)
-{
- assert(new_table_base >= MEMORY_OFFSET);
- assert(new_table_bytes == ARM_L1_ALIGN);
- assert(aligned(new_table_base, ARM_L1_ALIGN));
-
- lvaddr_t ttbr = local_phys_to_mem(cp15_read_ttbr0());
- size_t st = (MEMORY_OFFSET / ARM_L1_SECTION_BYTES) * ARM_L1_BYTES_PER_ENTRY;
-
- // Copy kernel pages (everything from MEMORY_OFFSET upwards)
- memcpy((void*)new_table_base + st, (void*)ttbr + st,
- ARM_L1_MAX_ENTRIES * ARM_L1_BYTES_PER_ENTRY - st);
-}
-
-void paging_map_user_pages_l1(lvaddr_t table_base, lvaddr_t va, lpaddr_t pa)
-{
- assert(aligned(table_base, ARM_L1_ALIGN));
- assert(aligned(pa, BYTES_PER_SMALL_PAGE));
-
- union arm_l1_entry e;
-
- e.raw = 0;
- e.page_table.type = L1_TYPE_PAGE_TABLE_ENTRY;
- e.page_table.domain = 0;
- e.page_table.base_address = (pa >> 10);
-
- paging_write_l1_entry(table_base, va, e);
-}
-
-void paging_set_l2_entry(uintptr_t* l2e, lpaddr_t addr, uintptr_t flags)
-{
- assert(0 == (flags & 0xfffff000));
- assert(0 == (flags & 0x3));
- assert(0 == (addr & 0xfff));
-
- union arm_l2_entry e;
- e.raw = flags;
-
- e.small_page.type = L2_TYPE_SMALL_PAGE;
- e.small_page.base_address = (addr >> 12);
-
- *l2e = e.raw;
-}
-
-void paging_context_switch(lpaddr_t ttbr)
-{
- assert(ttbr < MEMORY_OFFSET);
- //assert((ttbr & 0x3fff) == 0);
-
- lpaddr_t old_ttbr = cp15_read_ttbr0();
- if (ttbr != old_ttbr)
- {
- cp15_write_ttbr0(ttbr);
- cp15_invalidate_tlb();
- //this isn't necessary on gem5, since gem5 doesn't implement the cache
- //maintenance instructions, but ensures coherency by itself
- //cp15_invalidate_i_and_d_caches();
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2009, 2010 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <dispatch.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <barrelfish_kpi/init.h>
-#include <barrelfish_kpi/syscalls.h>
-#include <elf/elf.h>
-
-#include <arm_hal.h>
-#include <paging_kernel_arch.h>
-#include <exceptions.h>
-#include <cp15.h>
-#include <cpiobin.h>
-#include <init.h>
-#include <barrelfish_kpi/paging_arm_v7.h>
-#include <barrelfish_kpi/arm_core_data.h>
-#include <kernel_multiboot.h>
-#include <offsets.h>
-#include <startup_arch.h>
-#include <global.h>
-#include <kcb.h>
-
-#define CNODE(cte) (cte)->cap.u.cnode.cnode
-#define UNUSED(x) (x) = (x)
-
-#define STARTUP_PROGRESS() debug(SUBSYS_STARTUP, "%s:%d\n", \
- __FUNCTION__, __LINE__);
-
-#define BSP_INIT_MODULE_NAME BF_BINARY_PREFIX "armv7/sbin/init"
-#define APP_INIT_MODULE_NAME BF_BINARY_PREFIX "armv7/sbin/monitor"
-
-
-
-//static phys_mmap_t* g_phys_mmap; // Physical memory map
-static union arm_l1_entry * init_l1; // L1 page table for init
-static union arm_l2_entry * init_l2; // L2 page tables for init
-
-static struct spawn_state spawn_state;
-
-/// Pointer to bootinfo structure for init
-struct bootinfo* bootinfo = (struct bootinfo*)INIT_BOOTINFO_VBASE;
-
-/**
- * Each kernel has a local copy of global and locks. However, during booting and
- * kernel relocation, these are set to point to global of the pristine kernel,
- * so that all the kernels can share it.
- */
-//static struct global myglobal;
-struct global *global = (struct global *)GLOBAL_VBASE;
-
-static inline uintptr_t round_up(uintptr_t value, size_t unit)
-{
- assert(0 == (unit & (unit - 1)));
- size_t m = unit - 1;
- return (value + m) & ~m;
-}
-
-static inline uintptr_t round_down(uintptr_t value, size_t unit)
-{
- assert(0 == (unit & (unit - 1)));
- size_t m = unit - 1;
- return value & ~m;
-}
-
-// Physical memory allocator for spawn_app_init
-static lpaddr_t app_alloc_phys_start, app_alloc_phys_end;
-static lpaddr_t app_alloc_phys(size_t size)
-{
- uint32_t npages = (size + BASE_PAGE_SIZE - 1) / BASE_PAGE_SIZE;
-
-
- lpaddr_t addr = app_alloc_phys_start;
- app_alloc_phys_start += npages * BASE_PAGE_SIZE;
-
- if (app_alloc_phys_start >= app_alloc_phys_end) {
- panic("Out of memory, increase CORE_DATA_PAGES");
- }
-
- return addr;
-}
-
-static lpaddr_t app_alloc_phys_aligned(size_t size, size_t align)
-{
- app_alloc_phys_start = round_up(app_alloc_phys_start, align);
- return app_alloc_phys(size);
-}
-
-/**
- * The address from where bsp_alloc_phys will start allocating memory
- */
-static lpaddr_t bsp_init_alloc_addr = 0;
-
-/**
- * \brief Linear physical memory allocator.
- *
- * This function allocates a linear region of addresses of size 'size' from
- * physical memory.
- *
- * \param size Number of bytes to allocate.
- *
- * \return Base physical address of memory region.
- */
-static lpaddr_t bsp_alloc_phys(size_t size)
-{
- // round to base page size
- uint32_t npages = (size + BASE_PAGE_SIZE - 1) / BASE_PAGE_SIZE;
-
- assert(bsp_init_alloc_addr != 0);
-
- lpaddr_t addr = bsp_init_alloc_addr;
-
- bsp_init_alloc_addr += npages * BASE_PAGE_SIZE;
- return addr;
-}
-
-static lpaddr_t bsp_alloc_phys_aligned(size_t size, size_t align)
-{
- bsp_init_alloc_addr = round_up(bsp_init_alloc_addr, align);
- return bsp_alloc_phys(size);
-}
-
-/**
- * Map frames into init process address space. Init has a contiguous set of
- * l2 entries so this is straightforward.
- *
- * @param l2_table pointer to init's L2 table.
- * @param l2_base virtual address represented by first L2 table entry
- * @param va_base virtual address to map.
- * @param pa_base physical address to associate with virtual address.
- * @param bytes number of bytes to map.
- * @param l2_flags ARM L2 small page flags for mapped pages.
- */
-static void
-spawn_init_map(union arm_l2_entry* l2_table,
- lvaddr_t l2_base,
- lvaddr_t va_base,
- lpaddr_t pa_base,
- size_t bytes,
- uintptr_t l2_flags)
-{
- assert(va_base >= l2_base);
- assert(0 == (va_base & (BASE_PAGE_SIZE - 1)));
- assert(0 == (pa_base & (BASE_PAGE_SIZE - 1)));
- assert(0 == (bytes & (BASE_PAGE_SIZE - 1)));
-
- int bi = (va_base - l2_base) / BASE_PAGE_SIZE;
- int li = bi + bytes / BASE_PAGE_SIZE;
-
- while (bi < li)
- {
- paging_set_l2_entry((uintptr_t *)&l2_table[bi], pa_base, l2_flags);
- pa_base += BASE_PAGE_SIZE;
- bi++;
- }
-}
-
-static uint32_t elf_to_l2_flags(uint32_t eflags)
-{
- switch (eflags & (PF_W|PF_R))
- {
- case PF_W|PF_R:
- return (ARM_L2_SMALL_USR_RW |
- ARM_L2_SMALL_CACHEABLE |
- ARM_L2_SMALL_BUFFERABLE);
- case PF_R:
- return (ARM_L2_SMALL_USR_RO |
- ARM_L2_SMALL_CACHEABLE |
- ARM_L2_SMALL_BUFFERABLE);
- default:
- panic("Unknown ELF flags combination.");
- }
-}
-
-struct startup_l2_info
-{
- union arm_l2_entry* l2_table;
- lvaddr_t l2_base;
-};
-
-static errval_t
-startup_alloc_init(
- void* state,
- genvaddr_t gvbase,
- size_t bytes,
- uint32_t flags,
- void** ret
- )
-{
- const struct startup_l2_info* s2i = (const struct startup_l2_info*)state;
-
- lvaddr_t sv = round_down((lvaddr_t)gvbase, BASE_PAGE_SIZE);
- size_t off = (lvaddr_t)gvbase - sv;
- lvaddr_t lv = round_up((lvaddr_t)gvbase + bytes, BASE_PAGE_SIZE);
- lpaddr_t pa;
-
- //STARTUP_PROGRESS();
- if(hal_cpu_is_bsp())
- pa = bsp_alloc_phys_aligned((lv - sv), BASE_PAGE_SIZE);
- else
- pa = app_alloc_phys_aligned((lv - sv), BASE_PAGE_SIZE);
-
- if (lv > sv && (pa != 0))
- {
- spawn_init_map(s2i->l2_table, s2i->l2_base, sv,
- pa, lv - sv, elf_to_l2_flags(flags));
- *ret = (void*)(local_phys_to_mem(pa) + off);
- }
- else
- {
- *ret = 0;
- }
- return SYS_ERR_OK;
-}
-
-static void
-load_init_image(
- struct startup_l2_info* l2i,
- const char *name,
- genvaddr_t* init_ep,
- genvaddr_t* got_base
- )
-{
- lvaddr_t elf_base;
- size_t elf_bytes;
- errval_t err;
-
-
- *init_ep = *got_base = 0;
-
- /* Load init ELF32 binary */
- struct multiboot_modinfo *module = multiboot_find_module(name);
- if (module == NULL) {
- panic("Could not find init module!");
- }
-
- elf_base = local_phys_to_mem(module->mod_start);
- elf_bytes = MULTIBOOT_MODULE_SIZE(*module);
-
- debug(SUBSYS_STARTUP, "load_init_image %p %08x\n", elf_base, elf_bytes);
- //printf("load_init_image %p %08x\n", elf_base, elf_bytes);
-
- err = elf_load(EM_ARM, startup_alloc_init, l2i,
- elf_base, elf_bytes, init_ep);
- if (err_is_fail(err)) {
- //err_print_calltrace(err);
- panic("ELF load of " BSP_INIT_MODULE_NAME " failed!\n");
- }
-
- // TODO: Fix application linkage so that it's non-PIC.
- struct Elf32_Shdr* got_shdr =
- elf32_find_section_header_name((lvaddr_t)elf_base, elf_bytes, ".got");
- if (got_shdr)
- {
- *got_base = got_shdr->sh_addr;
- }
-}
-
-/// Setup the module cnode, which contains frame caps to all multiboot modules
-void create_module_caps(struct spawn_state *st)
-{
- errval_t err;
-
- /* Create caps for multiboot modules */
- struct multiboot_modinfo *module =
- (struct multiboot_modinfo *)local_phys_to_mem(glbl_core_data->mods_addr);
-
- // Allocate strings area
- lpaddr_t mmstrings_phys = bsp_alloc_phys(BASE_PAGE_SIZE);
- lvaddr_t mmstrings_base = local_phys_to_mem(mmstrings_phys);
- lvaddr_t mmstrings = mmstrings_base;
-
- // create cap for strings area in first slot of modulecn
- assert(st->modulecn_slot == 0);
- err = caps_create_new(ObjType_Frame, mmstrings_phys, BASE_PAGE_BITS,
- BASE_PAGE_BITS, my_core_id,
- caps_locate_slot(CNODE(st->modulecn),
- st->modulecn_slot++));
- assert(err_is_ok(err));
-
- /* Walk over multiboot modules, creating frame caps */
- for (int i = 0; i < glbl_core_data->mods_count; i++) {
- struct multiboot_modinfo *m = &module[i];
-
- // Set memory regions within bootinfo
- struct mem_region *region =
- &bootinfo->regions[bootinfo->regions_length++];
-
- genpaddr_t remain = MULTIBOOT_MODULE_SIZE(*m);
- genpaddr_t base_addr = local_phys_to_gen_phys(m->mod_start);
-
- region->mr_type = RegionType_Module;
- region->mr_base = base_addr;
- region->mrmod_slot = st->modulecn_slot; // first slot containing caps
- region->mrmod_size = remain; // size of image _in bytes_
- region->mrmod_data = mmstrings - mmstrings_base; // offset of string in area
-
- // round up to page size for caps
- remain = ROUND_UP(remain, BASE_PAGE_SIZE);
-
- // Create max-sized caps to multiboot module in module cnode
- while (remain > 0) {
- assert((base_addr & BASE_PAGE_MASK) == 0);
- assert((remain & BASE_PAGE_MASK) == 0);
-
- // determine size of next chunk
- uint8_t block_size = bitaddralign(remain, base_addr);
-
- assert(st->modulecn_slot < (1UL << st->modulecn->cap.u.cnode.bits));
- // create as DevFrame cap to avoid zeroing memory contents
- err = caps_create_new(ObjType_DevFrame, base_addr, block_size,
- block_size, my_core_id,
- caps_locate_slot(CNODE(st->modulecn),
- st->modulecn_slot++));
- assert(err_is_ok(err));
-
- // Advance by that chunk
- base_addr += ((genpaddr_t)1 << block_size);
- remain -= ((genpaddr_t)1 << block_size);
- }
-
- // Copy multiboot module string to mmstrings area
- strcpy((char *)mmstrings, MBADDR_ASSTRING(m->string));
- mmstrings += strlen(MBADDR_ASSTRING(m->string)) + 1;
- assert(mmstrings < mmstrings_base + BASE_PAGE_SIZE);
- }
-}
-
-/// Create physical address range or RAM caps to unused physical memory
-static void create_phys_caps(lpaddr_t init_alloc_addr)
-{
- errval_t err;
-
- /* Walk multiboot MMAP structure, and create appropriate caps for memory */
- char *mmap_addr = MBADDR_ASSTRING(glbl_core_data->mmap_addr);
- genpaddr_t last_end_addr = 0;
-
- for(char *m = mmap_addr; m < mmap_addr + glbl_core_data->mmap_length;)
- {
- struct multiboot_mmap *mmap = (struct multiboot_mmap * SAFE)TC(m);
-
- debug(SUBSYS_STARTUP, "MMAP %llx--%llx Type %"PRIu32"\n",
- mmap->base_addr, mmap->base_addr + mmap->length,
- mmap->type);
-
- if (last_end_addr >= init_alloc_addr
- && mmap->base_addr > last_end_addr)
- {
- /* we have a gap between regions. add this as a physaddr range */
- debug(SUBSYS_STARTUP, "physical address range %llx--%llx\n",
- last_end_addr, mmap->base_addr);
-
- err = create_caps_to_cnode(last_end_addr,
- mmap->base_addr - last_end_addr,
- RegionType_PhyAddr, &spawn_state, bootinfo);
- assert(err_is_ok(err));
- }
-
- if (mmap->type == MULTIBOOT_MEM_TYPE_RAM)
- {
- genpaddr_t base_addr = mmap->base_addr;
- genpaddr_t end_addr = base_addr + mmap->length;
-
- // only map RAM which is greater than init_alloc_addr
- if (end_addr > local_phys_to_gen_phys(init_alloc_addr))
- {
- if (base_addr < local_phys_to_gen_phys(init_alloc_addr)) {
- base_addr = local_phys_to_gen_phys(init_alloc_addr);
- }
- debug(SUBSYS_STARTUP, "RAM %llx--%llx\n", base_addr, end_addr);
-
- assert(end_addr >= base_addr);
- err = create_caps_to_cnode(base_addr, end_addr - base_addr,
- RegionType_Empty, &spawn_state, bootinfo);
- assert(err_is_ok(err));
- }
- }
- else if (mmap->base_addr > local_phys_to_gen_phys(init_alloc_addr))
- {
- /* XXX: The multiboot spec just says that mapping types other than
- * RAM are "reserved", but GRUB always maps the ACPI tables as type
- * 3, and things like the IOAPIC tend to show up as type 2 or 4,
- * so we map all these regions as platform data
- */
- debug(SUBSYS_STARTUP, "platform %llx--%llx\n", mmap->base_addr,
- mmap->base_addr + mmap->length);
- assert(mmap->base_addr > local_phys_to_gen_phys(init_alloc_addr));
- err = create_caps_to_cnode(mmap->base_addr, mmap->length,
- RegionType_PlatformData, &spawn_state, bootinfo);
- assert(err_is_ok(err));
- }
- last_end_addr = mmap->base_addr + mmap->length;
- m += mmap->size + 4;
- }
-
- // Assert that we have some physical address space
- assert(last_end_addr != 0);
-
- if (last_end_addr < PADDR_SPACE_SIZE)
- {
- /*
- * FIXME: adding the full range results in too many caps to add
- * to the cnode (and we can't handle such big caps in user-space
- * yet anyway) so instead we limit it to something much smaller
- */
- genpaddr_t size = PADDR_SPACE_SIZE - last_end_addr;
- const genpaddr_t phys_region_limit = 1ULL << 32; // PCI implementation limit
- if (last_end_addr > phys_region_limit) {
- size = 0; // end of RAM is already too high!
- } else if (last_end_addr + size > phys_region_limit) {
- size = phys_region_limit - last_end_addr;
- }
- debug(SUBSYS_STARTUP, "end physical address range %llx--%llx\n",
- last_end_addr, last_end_addr + size);
- err = create_caps_to_cnode(last_end_addr, size,
- RegionType_PhyAddr, &spawn_state, bootinfo);
- assert(err_is_ok(err));
- }
-}
-
-static void init_page_tables(void)
-{
- // Create page table for init
- if(hal_cpu_is_bsp())
- {
- init_l1 = (union arm_l1_entry *)local_phys_to_mem(bsp_alloc_phys_aligned(INIT_L1_BYTES, ARM_L1_ALIGN));
- memset(init_l1, 0, INIT_L1_BYTES);
-
- init_l2 = (union arm_l2_entry *)local_phys_to_mem(bsp_alloc_phys_aligned(INIT_L2_BYTES, ARM_L2_ALIGN));
- memset(init_l2, 0, INIT_L2_BYTES);
- }
- else
- {
- init_l1 = (union arm_l1_entry *)local_phys_to_mem(app_alloc_phys_aligned(INIT_L1_BYTES, ARM_L1_ALIGN));
- memset(init_l1, 0, INIT_L1_BYTES);
-
- init_l2 = (union arm_l2_entry *)local_phys_to_mem(app_alloc_phys_aligned(INIT_L2_BYTES, ARM_L2_ALIGN));
- memset(init_l2, 0, INIT_L2_BYTES);
- }
-
-
- /* Map pagetables into page CN */
- int pagecn_pagemap = 0;
-
- /*
- * ARM has:
- *
- * L1 has 4096 entries (16KB).
- * L2 Coarse has 256 entries (256 * 4B = 1KB).
- *
- * CPU driver currently fakes having 1024 entries in L1 and
- * L2 with 1024 entries by treating a page as 4 consecutive
- * L2 tables and mapping this as a unit in L1.
- */
- caps_create_new(
- ObjType_VNode_ARM_l1,
- mem_to_local_phys((lvaddr_t)init_l1),
- vnode_objbits(ObjType_VNode_ARM_l1), 0,
- my_core_id,
- caps_locate_slot(CNODE(spawn_state.pagecn), pagecn_pagemap++)
- );
-
- //STARTUP_PROGRESS();
-
- // Map L2 into successive slots in pagecn
- size_t i;
- for (i = 0; i < INIT_L2_BYTES / BASE_PAGE_SIZE; i++) {
- size_t objbits_vnode = vnode_objbits(ObjType_VNode_ARM_l2);
- assert(objbits_vnode == BASE_PAGE_BITS);
- caps_create_new(
- ObjType_VNode_ARM_l2,
- mem_to_local_phys((lvaddr_t)init_l2) + (i << objbits_vnode),
- objbits_vnode, 0,
- my_core_id,
- caps_locate_slot(CNODE(spawn_state.pagecn), pagecn_pagemap++)
- );
- }
-
- /*
- * Initialize init page tables - this just wires the L1
- * entries through to the corresponding L2 entries.
- */
- STATIC_ASSERT(0 == (INIT_VBASE % ARM_L1_SECTION_BYTES), "");
- for (lvaddr_t vaddr = INIT_VBASE; vaddr < INIT_SPACE_LIMIT; vaddr += ARM_L1_SECTION_BYTES)
- {
- uintptr_t section = (vaddr - INIT_VBASE) / ARM_L1_SECTION_BYTES;
- uintptr_t l2_off = section * ARM_L2_TABLE_BYTES;
- lpaddr_t paddr = mem_to_local_phys((lvaddr_t)init_l2) + l2_off;
- paging_map_user_pages_l1((lvaddr_t)init_l1, vaddr, paddr);
- }
-
- paging_context_switch(mem_to_local_phys((lvaddr_t)init_l1));
-}
-
-static struct dcb *spawn_init_common(const char *name,
- int argc, const char *argv[],
- lpaddr_t bootinfo_phys,
- alloc_phys_func alloc_phys)
-{
- lvaddr_t paramaddr;
- struct dcb *init_dcb = spawn_module(&spawn_state, name,
- argc, argv,
- bootinfo_phys, INIT_ARGS_VBASE,
- alloc_phys, ¶maddr);
-
- init_page_tables();
-
- init_dcb->vspace = mem_to_local_phys((lvaddr_t)init_l1);
-
- spawn_init_map(init_l2, INIT_VBASE, INIT_ARGS_VBASE,
- spawn_state.args_page, ARGS_SIZE, INIT_PERM_RW);
-
-
- // Map dispatcher
- spawn_init_map(init_l2, INIT_VBASE, INIT_DISPATCHER_VBASE,
- mem_to_local_phys(init_dcb->disp), DISPATCHER_SIZE,
- INIT_PERM_RW);
-
-
- /*
- * Create a capability that allows user-level applications to
- * access device memory. This capability will be passed to Kaluga,
- * split up into smaller pieces and distributed to among device
- * drivers.
- *
- * For arm_gem5, this is currently a dummy capability. We do not
- * have support for user-level device drivers in gem5 yet, so we
- * do not allocate any memory as device memory. Some cap_copy
- * operations in the bootup code fail if this capability is not
- * present.
- */
- struct cte *iocap = caps_locate_slot(CNODE(spawn_state.taskcn), TASKCN_SLOT_IO);
- errval_t err = caps_create_new(ObjType_IO, 0, 0, 0, my_core_id, iocap);
- assert(err_is_ok(err));
-
- struct dispatcher_shared_generic *disp
- = get_dispatcher_shared_generic(init_dcb->disp);
- struct dispatcher_shared_arm *disp_arm
- = get_dispatcher_shared_arm(init_dcb->disp);
-
- /* Initialize dispatcher */
- disp->disabled = true;
- strncpy(disp->name, argv[0], DISP_NAME_LEN);
-
- /* tell init the vspace addr of its dispatcher */
- disp->udisp = INIT_DISPATCHER_VBASE;
-
- disp_arm->enabled_save_area.named.r0 = paramaddr;
- disp_arm->enabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK;
- disp_arm->enabled_save_area.named.rtls = INIT_DISPATCHER_VBASE;
- disp_arm->disabled_save_area.named.rtls = INIT_DISPATCHER_VBASE;
-
-
- return init_dcb;
-}
-
-struct dcb *spawn_bsp_init(const char *name, alloc_phys_func alloc_phys)
-{
- /* Only the first core can run this code */
- assert(hal_cpu_is_bsp());
-
- /* Allocate bootinfo */
- lpaddr_t bootinfo_phys = alloc_phys(BOOTINFO_SIZE);
- memset((void *)local_phys_to_mem(bootinfo_phys), 0, BOOTINFO_SIZE);
-
- /* Construct cmdline args */
- char bootinfochar[16];
- snprintf(bootinfochar, sizeof(bootinfochar), "%u", INIT_BOOTINFO_VBASE);
- const char *argv[] = { "init", bootinfochar };
- int argc = 2;
-
- struct dcb *init_dcb = spawn_init_common(name, argc, argv,bootinfo_phys, alloc_phys);
-
- // Map bootinfo
- spawn_init_map(init_l2, INIT_VBASE, INIT_BOOTINFO_VBASE,
- bootinfo_phys, BOOTINFO_SIZE , INIT_PERM_RW);
-
- struct startup_l2_info l2_info = { init_l2, INIT_VBASE };
-
- genvaddr_t init_ep, got_base;
- load_init_image(&l2_info, BSP_INIT_MODULE_NAME, &init_ep, &got_base);
-
- struct dispatcher_shared_arm *disp_arm
- = get_dispatcher_shared_arm(init_dcb->disp);
- disp_arm->enabled_save_area.named.r10 = got_base;
- disp_arm->got_base = got_base;
-
- disp_arm->disabled_save_area.named.pc = init_ep;
- disp_arm->disabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK;
- disp_arm->disabled_save_area.named.r10 = got_base;
-
- /* Create caps for init to use */
- create_module_caps(&spawn_state);
- lpaddr_t init_alloc_end = alloc_phys(0); // XXX
- create_phys_caps(init_alloc_end);
-
- /* Fill bootinfo struct */
- bootinfo->mem_spawn_core = KERNEL_IMAGE_SIZE; // Size of kernel
-
- /*
- // Map dispatcher
- spawn_init_map(init_l2, INIT_VBASE, INIT_DISPATCHER_VBASE,
- mem_to_local_phys(init_dcb->disp), DISPATCHER_SIZE,
- INIT_PERM_RW);
- disp_arm->disabled_save_area.named.rtls = INIT_DISPATCHER_VBASE;
- */
- return init_dcb;
-}
-
-struct dcb *spawn_app_init(struct arm_core_data *core_data,
- const char *name, alloc_phys_func alloc_phys)
-{
- errval_t err;
-
- /* Construct cmdline args */
- // Core id of the core that booted this core
- char coreidchar[10];
- snprintf(coreidchar, sizeof(coreidchar), "%d", core_data->src_core_id);
-
- // IPI channel id of core that booted this core
- char chanidchar[30];
- snprintf(chanidchar, sizeof(chanidchar), "chanid=%"PRIu32, core_data->chan_id);
-
- // Arch id of the core that booted this core
- char archidchar[30];
- snprintf(archidchar, sizeof(archidchar), "archid=%d",
- core_data->src_arch_id);
-
- const char *argv[5] = { name, coreidchar, chanidchar, archidchar };
- int argc = 4;
-
- struct dcb *init_dcb = spawn_init_common(name, argc, argv,0, alloc_phys);
-
- // Urpc frame cap
- struct cte *urpc_frame_cte = caps_locate_slot(CNODE(spawn_state.taskcn),
- TASKCN_SLOT_MON_URPC);
- // XXX: Create as devframe so the memory is not zeroed out
- err = caps_create_new(ObjType_DevFrame, core_data->urpc_frame_base,
- core_data->urpc_frame_bits, core_data->urpc_frame_bits,
- my_core_id, urpc_frame_cte);
- assert(err_is_ok(err));
- urpc_frame_cte->cap.type = ObjType_Frame;
- lpaddr_t urpc_ptr = gen_phys_to_local_phys(urpc_frame_cte->cap.u.frame.base);
-
- /* Map urpc frame at MON_URPC_BASE */
- spawn_init_map(init_l2, INIT_VBASE, MON_URPC_VBASE, urpc_ptr, MON_URPC_SIZE,
- INIT_PERM_RW);
-
- struct startup_l2_info l2_info = { init_l2, INIT_VBASE };
-
- // elf load the domain
- genvaddr_t entry_point, got_base=0;
- err = elf_load(EM_ARM, startup_alloc_init, &l2_info,
- local_phys_to_mem(core_data->monitor_binary),
- core_data->monitor_binary_size, &entry_point);
- if (err_is_fail(err)) {
- //err_print_calltrace(err);
- panic("ELF load of init module failed!");
- }
-
- // TODO: Fix application linkage so that it's non-PIC.
- struct Elf32_Shdr* got_shdr =
- elf32_find_section_header_name(local_phys_to_mem(core_data->monitor_binary),
- core_data->monitor_binary_size, ".got");
- if (got_shdr)
- {
- got_base = got_shdr->sh_addr;
- }
-
- struct dispatcher_shared_arm *disp_arm =
- get_dispatcher_shared_arm(init_dcb->disp);
- disp_arm->enabled_save_area.named.r10 = got_base;
- disp_arm->got_base = got_base;
-
- disp_arm->disabled_save_area.named.pc = entry_point;
- disp_arm->disabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK;
- disp_arm->disabled_save_area.named.r10 = got_base;
- //disp_arm->disabled_save_area.named.rtls = INIT_DISPATCHER_VBASE;
-
- return init_dcb;
-}
-
-void arm_kernel_startup(void)
-{
- /* Initialize the core_data */
- /* Used when bringing up other cores, must be at consistent global address
- * seen by all cores */
- struct arm_core_data *core_data =
- (void *) ((lvaddr_t)&kernel_first_byte - BASE_PAGE_SIZE);
-
- struct dcb *init_dcb;
-
- if (hal_cpu_is_bsp()) {
- /* Initialize the location to allocate phys memory from */
- printf("start_free_ram = 0x%lx\n", glbl_core_data->start_free_ram);
- bsp_init_alloc_addr = glbl_core_data->start_free_ram;
-
- /* allocate initial KCB */
- kcb_current = (struct kcb *) local_phys_to_mem(bsp_alloc_phys(sizeof(*kcb_current)));
- memset(kcb_current, 0, sizeof(*kcb_current));
- assert(kcb_current);
-
- /* spawn init */
- init_dcb = spawn_bsp_init(BSP_INIT_MODULE_NAME, bsp_alloc_phys);
-
- pit_start(0);
-
- } else {
- kcb_current = (struct kcb *)
- local_phys_to_mem((lpaddr_t) kcb_current);
-
- my_core_id = core_data->dst_core_id;
-
- /* Initialize the allocator */
- app_alloc_phys_start = core_data->memory_base_start;
- app_alloc_phys_end = ((lpaddr_t)1 << core_data->memory_bits) +
- app_alloc_phys_start;
-
- init_dcb = spawn_app_init(core_data, APP_INIT_MODULE_NAME, app_alloc_phys);
-
- uint32_t irq = gic_get_active_irq();
- gic_ack_irq(irq);
- }
-
- // enable interrupt forwarding to cpu
- gic_cpu_interface_enable();
-
- // Should not return
- dispatch(init_dcb);
- panic("Error spawning init!");
-
-}
+++ /dev/null
-/**
- * \file
- * \brief Bootstrap the kernel.
- */
-/*
- * Copyright (c) 2009 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#ifndef __ASSEMBLER__
-#define __ASSEMBLER__ 1
-#endif
-
-#include <barrelfish_kpi/flags_arch.h> // ARM_MODE_MASK
-#include <offsets.h> // BOOT_STACK_PHYS
-
- .text
- .arm
-
- .globl start, halt, got_base
-
- // Used to track phys memory allocator limit globally.
- alloc_top .req r11
-
-start:
- // Entry constraints same as ARM Linux so QEMU can boot
- // this file directly and to make it easy to use existing
- // loaders on real h/w.
- //
- // The build process has built an ELF kernel image. The first
- // word is overwritten to branch to entry point, `start', in
- // the text section of the unpacked ELF file. The start routine
- // then loads the ELF image, initializes the page table, and
- // enables paging.
- //
- // NB Writing the branch instruction into the first word of the
- // ELF header causes QEMU to treat the file as a Linux kernel
- // image and it provides the ATAG_HEADER info.
- //
- // On entry:
- //
- // MMU disabled
- // Caches in unknown state, but no lockdown
- // No TLB lockdown.
- // CPU is in a priveledged mode.
- //
- // r0 contains zero
- // r1 contains board id
- // r2 contains pointer to kernel args structure
- // lr contains pointer to elf header + 4
-
- sub lr, lr, #4 // lr = address of elf header
- mov r4, lr // r4 = p_elf_header [KEEP]
-
- mrs r3, cpsr // Ensure in SYS mode
- bic r3, r3, #ARM_MODE_MASK
- orr r3, r3, #ARM_MODE_SYS
- msr cpsr_c, r3
-
- mov sp, #BOOT_STACK_PHYS
- stmfd sp!, {r1, r2}
-
- /* Validate ELF header */
- mov r0, r4
- bl elf_header_is_valid
- cmp r0, #0
- beq .
-
- /* Compute size of elf file */
- mov r0, r4 // r0 = p_elf_header
- bl elf_get_file_size // r0 = elf_file_size
- mov r5, r0 // r5 = elf_file_size [KEEP]
-
- mov r0, r4
- bl elf_get_expanded_limits
-
- mov r6, r0 // r6 = kernel v_addr [KEEP]
- mov r7, r1 // r7 = kernel v_limit [KEEP]
-
- /* Want to map low 1MB section with 1:1 to kernel address space */
- mov r2, #(512 * 1024 * 1024)
- cmp pc, r2
- bhs start_rom_image
-
- /*
- The ELF image is in RAM, copy it just above the
- physical pages of the unpacked kernel (1:1 mapping
- between kernel v_addr and p_addr).
- */
-
- ldr r3, =4095 // Page align kernel v_limit
- add r0, r7, r3
- orr r3, r3, r3, LSL #20
- bic r0, r0, r3 // r0 = new ELF file physical address
- mov r1, r4 // r1 = old ELF file physical address
- mov r2, r5 // r2 = ELF size
- sub r8, r0, r1 // r8 = delta (new, old) ELF physical address
- bl memcpy
-
- add r4, r4, r8 // Update r4, p_elf_header
- sub r8, r8, #4
- add pc, pc, r8 // Jump to next line, but in relocated ELF image.
-
-start_rom_image:
- // NOP
-
-start_expand_elf:
- // Zero physical region
- sub r1, r7, r6 // r1 = expanded ELF size
- ldr r2, =0xfff00000
- bic r0, r6, r2 // r0 = physical address of expanded image
- bl memzero
-
- // Expand file
- ldr r2, =0xfff00000
- bic r2, r6, r2 // r2 = kernel p_addr
- mov r1, r6 // r1 = kernel v_addr
- mov r0, r4 // r0 = elf_header
- bl elf_expand
-
- add alloc_top, r4, r5 // alloc_top = end of ELF file.
-
- mov r0, #16384 // allocate L1 page table (16K aligned to 16K).
- mov r1, r0
- bl alloc_phys
- mov r8, r0 // r8 = L1 page table [KEEP]
-
-start_map_kernel:
- ldr r3, =0xfff00000 // Map kernel section to physical section
- and r1, r6, r3
- and r2, sp, r3
- bl section_map // section_map (l1_addr, v_addr, p_addr)
-
- ldr r3, =0xfff00000 // Map section containing program counter 1:1
- and r2, pc, r3
- mov r1, r1
- mov r0, r8
- bl section_map
-
-start_mmu_config:
- mcr p15, 0, r8, c2, c0, 0 // Load TTBR with L1
- ldr r0, =0x55555555 // Initial domain permissions - all client [checked]
- mcr p15, 0, r0, c3, c0, 0
-
- ldr lr, =start_with_mmu_enabled // Address to continue at when paging is enabled
- ldr r0, =KERNEL_OFFSET
- add sp, sp, r0 // Prepare stack for relocation
-
- ldr r1, =0x1007 // Enable: D-Cache, I-Cache, Alignment, MMU
- mrc p15, 0, r0, c1, c0, 0
- orr r0, r0, r1
- mcr p15, 0, r0, c1, c0, 0 // MMU is enabled
- mov pc, lr // Flat fetched.
- mov r0, r0 // Flat fetched.
-
- // Up until this point PC is in ELF file.
-start_with_mmu_enabled:
- // MMU is enabled and PC is in the loaded ELF image.
-
- mov r1, #0 // Unmap section with VA = 0
- mov r0, r8 // r0 = page table address
- bl section_unmap
-
- mov r1, #0
- mcr p15, 0, r1, c8, c7, 0 // Invalidate ID-TLB entry for section with VA = 0.
-
-start_set_got_register:
- ldr PIC_REGISTER, =got_base
-
-start_set_init_arguments:
- ldmfd sp!, {r0, r1} // r0 = board id
- // r1 = paddr of kern args
- ldr r2, =KERNEL_OFFSET // Convert paddr's to vaddr's
- add r1, r1, r2 // r1 is now vaddr of kern args
- add r3, alloc_top, r2 // r3 = alloc_top
- add r2, r4, r2 // r2 = addr kernel ELF file
- mov lr, #0
- b arch_init
-
-/**
- * bool elf_header_is_valid(struct Elf32_EHdr*)
- *
- * A cursory check of ELF header. nb first word is known to be invalid
- */
-elf_header_is_valid:
- ldr r1, [r0, #4]! // e_ident[4..7]
- ldr r2, =0x00010101
- eors r3, r1, r2
- bne done
- ldr r1, [r0, #4]! // e_ident[8..11]
- mov r2, #0
- eors r3, r1, r2
- bne done
- ldr r1, [r0, #4]! // e_ident[12..15]
- eors r3, r1, r2
- bne done
- ldr r1, [r0, #4]! // (e_type, e_machine)
- ldr r2, =0x00280002
- eors r3, r1, r2
- bne done
- ldr r1, [r0, #4]! // e_version
- mov r2, #1
- eors r3, r1, r2
-done:
- mvn r3, r3
- bx lr
-
-/**
- * uint32_t elf_get_file_size(struct Elf32_EHdr*)
- */
-elf_get_file_size:
- ldr r1, [r0, #32] // r1 = offset of sections
- ldrh r2, [r0, #46] // r2 = e_shentsize
- ldrh r3, [r0, #48] // r3 = e_shnum
- mul r0, r2, r3
- add r0, r0, r1
- bx lr
-
-/**
- * (vaddr_t, size_t) elf_get_expanded_limits(struct Elf32_EHdr*)
- */
-elf_get_expanded_limits:
- stmfd sp!, {r4-r6, lr}
- mov r5, #0 // r5 = max vaddr
- sub r4, r5, #1 // r4 = min vaddr
- ldr r1, [r0, #28] // r1 = e_phoff
- ldrh r2, [r0, #42] // r2 = e_phentsize
- ldrh r3, [r0, #44] // r3 = e_phnum
- add r1, r1, r0 // r1 = start of prog headers
- mul r0, r2, r3 // r0 = size of prog headers
- add r3, r0, r1 // r3 = end of prog headers
- b looptest
-loopstart:
- ldr r6, [r1, #20] // r6 = memsz
- cmp r6, #0
- beq loopinc // SKIP If memsz = 0
- ldr r0, [r1, #8] // r0 = vaddr
- cmp r0, r4
- movlo r4, r0 // r4 = min(r4, vaddr)
- add r6, r0, r6 // r0 = vaddr + memsz
- cmp r6, r5
- movhs r5, r6 // r5 = max(r5, vaddr + memsz)
- ldr r0, [r1, #28] // r0 = alignment
-loopinc:
- add r1, r1, r2
-looptest:
- cmp r1, r3
- bne loopstart
- mov r0, r4
- mov r1, r5
- ldmfd sp!, {r4-r6, pc}
-
-/**
- * void elf_expand(Struct Elf32_EHdr*, vaddr_t kernel_v, paddr_t kernel_p)
- */
-elf_expand:
- stmfd sp!, {r4-r7, lr}
- ldr r3, [r0, #28] // r3 = e_phoff
- ldrh r4, [r0, #44] // r4 = e_phnum
- add r3, r0, r3 // r3 = addr phdr[0]
-elf_expand_start:
- subs r4, r4, #1
- beq elf_expand_done
- ldr r5, [r3, #4] // r5 = p_offset
- cmp r5, #0
- beq elf_expand_next
- ldr r6, [r3, #8] // r6 = p_vaddr
- cmp r6, #0
- beq elf_expand_next
- stmfd sp!, {r0-r3} // Save scratch registers
- mov r7, r1 // r7 = kernel_v
- add r1, r0, r5 // r1 = ptr to segment in file
- sub r0, r6, r7 // r0 = kernel_v_offset
- add r0, r0, r2 // r0 = phys addr of segment
- ldr r2, [r3, #16] // r2 = p_filesz
- bl memcpy
- ldmfd sp!, {r0-r3} // Restore scratch registers
-elf_expand_next:
- ldrh r5, [r0, #42] // r5 = e_phentsize
- add r3, r3, r5 // r3 = addr phdr[next]
- b elf_expand_start
-elf_expand_done:
- ldmfd sp!, {r4-r7, pc}
-
-/**
- * void memzero(uintptr_t addr, size_t bytes)
- * Assumes addr is 4-byte aligned and bytes is a multiple of 4.
- */
-memzero:
- subs r1, #4
- blt zero0
- mov r2, #0
- mov r3, #0
- subs r1, #12
- blt zero8
-zero16:
- stmia r0!, {r2-r3}
- subs r1, r1, #16
- stmia r0!, {r2-r3}
- bge zero16
-zero8:
- adds r1, r1, #8
- stmgeia r0!, {r2, r3}
- subge r1, #8
-zero4:
- adds r1, r1, #4
- stmgeia r0!, {r2}
-zero0:
- bx lr
-
-/**
- * void memcpy(uintptr_t dest, uintptr_t src, size_t bytes)
- *
- * Assumes addr is 4-byte aligned and bytes is a multiple of 4.
- */
-memcpy:
- stmfd sp!, {r4, r5, lr}
- subs r2, #16
- blt cpy8
-cpy16:
- ldmia r1!, {r4-r5}
- stmia r0!, {r4-r5}
- subs r2, r2, #16
- ldmia r1!, {r4-r5}
- stmia r0!, {r4-r5}
- bge cpy16
-cpy8:
- adds r2, r2, #8
- ldmgeia r1!, {r4, r5}
- subge r2, #8
- stmgeia r0!, {r4, r5}
-cpy4:
- adds r2, r2, #4
- ldrge r4, [r0], #4
- strge r4, [r1], #4
-cpy0:
- ldmfd sp!, {r4, r5, pc}
-
-/**
- * Allocate Physical Memory.
- *
- * uintptr_t alloc_phys(size_t bytes, size_t align)
- */
-alloc_phys:
- sub r1, r1, #1
- mov r3, alloc_top
- add r3, r3, r1 // Align start address
- bic r3, r3, r1 // r3 = alloc address
- add r0, r0, r3 // r0 = new alloc_top value
- mov alloc_top, r0
- stmfd sp!, {r3, lr}
- sub r1, r0, r3
- mov r0, r3
- bl memzero
- ldmfd sp!, {r0, pc}
-
-/**
- * void section_map(L1PageTable *p, vaddr_t v, paddr_t p)
- */
-section_map:
- lsr r1, r1, #20 // r1 is table offset
- lsr r2, r2, #20
- ldr r3, =0x41e // AP = 01, Domain = 0, CB, Section
- orr r2, r3, r2, LSL #20 // r2 = Section Entry
- str r2, [r0, r1, LSL #2] // table[v >> 20] = r2
- bx lr
-
-/**
- * void section_unmap(L1PageTable *p, vaddr_t v)
- */
-section_unmap:
- mov r2, #0 // Invalid L1 PTE
- str r2, [r0, r1, LSL #18]
- bx lr
-
-/**
- * extern "C" void halt(void) __attribute__((noreturn))
- */
-halt:
- b .
-
-.ltorg
-
-got_base:
- .word // Initialized by linker
-
- .end
+++ /dev/null
-/**
- * \file
- * \brief Cache control routines for ARMv5
- */
-/*
- * Copyright (c) 2009 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <cp15.h>
-
-// XXX: There is a function with the same name in arch/armv7/cp15.S;
-// we need to check wether can use a single function
-
-/*
- * IXP2800_Hardware_Reference_Manual, p.94 i-cache
- * IXP2800_Hardware_Reference_Manual, p.105 D-cache
- */
-void cp15_invalidate_i_and_d_caches(void)
-{
- uint32_t tmp_mem;
- uint32_t *tmp = &tmp_mem; //Use variable on stack as storage space. We need a safe place in virtual memory.
-
- __asm volatile(
- //Clean (write back) D-cache
- "MOV r0, #1024 \n\t"
- "LOOP1: \n\t"
- "MCR p15, 0, r1, c7, c2, 5\n\t"
- "ADD r1, r1, #32\n\t"
- "SUBS r0, r0, #1\n\t"
- "BNE LOOP1\n\t"
- "MOV r0, #64\n\t"
-
- //Clean (write back) mini D-cache
- "LOOP2:\n\t"
- "MOV r2, %[tmp]\n\t"
- "LDR r3, [r2], #32\n\t"
- "SUBS r0, r0, #1\n\t"
- "BNE LOOP2\n\t"
- "MCR p15, 0, r0, c7, c6, 0\n\t" //Invalidate D-cache
- "mcr p15, 0, r1, c7, c5, 0 \n\t" //Invalidate i-cache
- ::[tmp] "r" (tmp) : "r0", "r1", "r2", "r3");
-}
+++ /dev/null
-/*
- * Copyright (c) 2007, 2008, 2009, ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#ifndef __ASSEMBLER__
-#define __ASSEMBLER__
-#endif // __ASSEMBLER__
-
-#include <asmoffsets.h> // OFFSETOF etc.
-#include <barrelfish_kpi/registers_arch.h> // CPSR_REG etc.
-#include <barrelfish_kpi/flags_arch.h> // CPSR_IF_MASK etc.
-#include <exceptions.h>
-
-#define EXCEPTION_MODE_STACK_BYTES 256
-#define SYSTEM_MODE_STACK_BYTES 8192
-
- .arm
- .text
-
- .globl exceptions_init
- .globl pabt_handler
- //
- // Exception mode stacks
- //
- // These are small stacks used to figure out where to
- // spill registers. As these are banked functions are
- // expected to leave them as found (ie. so they do not
- // need to be reset next time around).
- //
- .align 4
-
-abt_stack:
- .space EXCEPTION_MODE_STACK_BYTES, 0
-abt_stack_top:
- .space 4, 0
-
-irq_stack:
- .space EXCEPTION_MODE_STACK_BYTES, 0
-irq_stack_top:
- .space 4, 0
-
-undef_stack:
- .space EXCEPTION_MODE_STACK_BYTES, 0
-undef_stack_top:
- .space 4, 0
-
-svc_stack:
- .space EXCEPTION_MODE_STACK_BYTES, 0
-svc_stack_top:
- .space 4, 0
-
- //
- // System mode stack
- //
- // This is used for calls to C routines.
- //
- // Users of this stack are expected to set sp_sys to this value
- // before calling C routines.
- //
-sys_stack:
- .space SYSTEM_MODE_STACK_BYTES, 0
-sys_stack_top:
-
-irq_save_area:
- .space (NUM_REGS * 4), 0
-
-got_for_sys_mode:
- .word 0
-
- //
- // void exceptions_init(void)
- //
- // Assumes running in System Mode.
- //
-exceptions_init:
- ldr r0, null_handler
- ldr r1, =ETABLE_ADDR
- mov r2, #7
-$exceptions_init_do_one:
- str r0, [r1], #4
- subs r2, r2, #1
- bpl $exceptions_init_do_one
-$exceptions_init_en_high:
- mrc p15, 0, r0, c1, c0, 0
- orr r0, r0, #0x2000
- mcr p15, 0, r0, c1, c0, 0
-$exceptions_load_stacks:
- stmfd sp!, {lr}
- mov r0, #ARM_MODE_ABT
- ldr r1, = abt_stack_top
- bl set_stack_for_mode
- mov r0, #ARM_MODE_IRQ
- ldr r1, = irq_stack_top
- bl set_stack_for_mode
- mov r0, # ARM_MODE_UND
- ldr r1, = undef_stack_top
- bl set_stack_for_mode
- mov r0, # ARM_MODE_SVC
- ldr r1, = svc_stack_top
- bl set_stack_for_mode
-$expections_install_handlers:
- mov r0, # ARM_EVECTOR_PABT
- adr r1, pabt_handler
- bl exceptions_install_handler
- mov r0, # ARM_EVECTOR_DABT
- adr r1, dabt_handler
- bl exceptions_install_handler
- mov r0, # ARM_EVECTOR_IRQ
- adr r1, irq_handler
- bl exceptions_install_handler
- mov r0, # ARM_EVECTOR_UNDEF
- adr r1, undef_handler
- bl exceptions_install_handler
- mov r0, # ARM_EVECTOR_SWI
- adr r1, swi_handler
- bl exceptions_install_handler
-$exceptions_save_got:
- ldr r0, = got_for_sys_mode
- str PIC_REGISTER, [r0]
-$exceptions_init_done:
- ldmfd sp!, {pc}
-
- //
- // void set_stack_for_mode(uint8_t cpu_mode, uintptr_t stack)
- //
-set_stack_for_mode:
- mrs r3, cpsr // Save current mode
- and r0, r0, # ARM_MODE_MASK
- bic r2, r3, # ARM_MODE_MASK
- orr r2, r2, r0
- msr cpsr_c, r2 // Switch to cpu_mode
- mov sp, r1
- msr cpsr_c, r3 // Switch back
- bx lr
-
- //
- // void exceptions_install_handler(int vector_offset,
- // void (*handler)(void)
- //
-exceptions_install_handler:
- ldr r2, = ETABLE_ADDR
- add r2, r2, r0
- sub r1, r1, r2
- subs r1, r1, #8
- lsr r1, r1, #2
- ldr r0, [r2]
- mov r3, #0xff000000
- and r0, r0, r3
- bic r1, r1, r3
- orr r0, r0, r1
- str r0, [r2]
- bx lr
-
- //
- // void null_handler(void)
- //
-null_handler:
- b .
-
- //
- // Macro definition to get pointer to arch specific dispatcher
- //
- // Logical equivalent of C function with same name
- //
-.macro get_dispatcher_shared_arm out
- ldr \out, = dcb_current // out = address of pointer to dcb_current
- ldr \out, [\out] // out = dcb_current
- ldr \out, [\out, #OFFSETOF_DCB_DISP] //now ptr to dispatcher_shared_arm
-.endm
-
- //
- // Macro to determine if dispatcher is disabled.
- //
- // pc and disp arguments are unmodified.
- // out contains result
- //
-.macro disp_is_disabled disp, pc, out
- // disp->disabled || (disp->crit_pc_lo <= pc && pc < disp->crit_pc_hi)
- ldrb \out, [\disp, #OFFSETOF_DISP_DISABLED]
- cmp \out, #1
- bhs 0f // disp->disabled >= 0 | disabled
- // disp->disabled = false
- ldr \out, [\disp, #OFFSETOF_DISP_CRIT_PC_LOW]
- cmp \out, \pc
- movhi \out, #0
- bhi 0f // disp->crit_pc_low > pc | enabled
- ldr \out, [\disp, #OFFSETOF_DISP_CRIT_PC_HIGH]
- cmp \pc, \out
- movhs \out, #0 // pc >= disp->crit_pc_high | enabled
- movlo \out, #1 // pc < disp->crit_pc_high | disable
-0:
-.endm
-
- //
- // Macro to spill registers
- //
- // Assumptions:
- // - context is in scratch registers set {r0-r3}.
- // - spsr is also in scratch register set.
- // - stack holds spilled scratch registers.
- // - lr contains pc for context
- // Side-effects:
- // - spills context
- // - pops scratch registers off stack (sp -> sp + 16).
- // - trashes spsr_reg
- //
-.macro save_context context, spsr_reg
- .if CPSR_REG <> 0
- .err "Invariant failure: CPSR offset != 0"
- .endif
- .if PC_REG <> 16
- .err "Invariant failure: PC offset != 16"
- .endif
- str \spsr_reg, [\context, #(CPSR_REG * 4)]
- str lr, [\context, #(PC_REG * 4)]
- add \spsr_reg, \context, #(LR_REG * 4)
- stmda \spsr_reg, {r4-r14}^
- add \spsr_reg, \context, #(R3_REG * 4)
- pop {r4-r7} // Pop spilled scratch registers
- stmda \spsr_reg!, {r4-r7} // And Save them
-.endm
-
- //
- // Macro to initialize system mode stack
- //
-.macro init_sys_stack
- ldr sp, =sys_stack_top
-.endm
-
- //
- // Macro to initialize SVC pic register
- //
-.macro init_sys_pic_register
- ldr PIC_REGISTER, = got_for_sys_mode
- ldr PIC_REGISTER, [PIC_REGISTER]
-.endm
-
- //
- // Macro to enter SYS mode with interrupts disabled.
- // Set up stack and GOT pointer.
- //
-.macro enter_sys scratch
- mov \scratch, #(CPSR_IF_MASK | ARM_MODE_SYS)
- msr cpsr_c, \scratch
- init_sys_pic_register
- init_sys_stack
-.endm
-
- //
- // void pabt_handler(void)
- //
- // Entered in ABT mode, IRQ disabled, ARM state.
- //
-pabt_handler:
- stmfd sp!, {r0-r3} // Save for scratch use
- sub lr, lr, #4 // lr = faulting pc
- mrs r3, spsr // r3 = spsr until save_context
- ands r1, r3, #ARM_MODE_PRIV
- bne $pabt_kernel
-$pabt_user:
- get_dispatcher_shared_arm r2
- mov r0, lr // r0 = faulting pc
- disp_is_disabled r2, r0, r1 // r1 = 1 if disabled, else 0
- cmp r1, #0
- addeq r1, r2, #OFFSETOF_DISP_ENABLED_AREA
- addne r1, r2, #OFFSETOF_DISP_TRAP_AREA
- save_context r1, r3 // r1 = save area
- enter_sys r3
- b handle_user_page_fault // f(fault_addr, save_area)
-$pabt_kernel:
- // {r0-r3} spilled to stack
- sub r2, sp, #(NUM_REGS * 4) // Reserve stack space for save
- save_context r2, r3 // r2 = save_area
- mov r1, lr // r1 = faulting pc
- mov r0, #ARM_EVECTOR_PABT
- enter_sys r3
- b fatal_kernel_fault // f(evector, addr, save_area)
-
- //
- // void dabt_handler(void)
- //
- // Entered in ABT mode, IRQ disabled, ARM state.
- //
-dabt_handler:
- stmfd sp!, {r0-r3} // Save for scratch use
- sub lr, lr, #8 // lr = faulting instruction
- mrs r3, spsr // r3 = spsr until save_context
- ands r1, r3, #ARM_MODE_PRIV
- bne $dabt_kernel
-$dabt_user:
- get_dispatcher_shared_arm r2
- mov r0, lr // r0 = faulting pc
- disp_is_disabled r2, r0, r1 // r1 = disp_is_disabled
- cmp r1, #0
- addeq r1, r2, #OFFSETOF_DISP_ENABLED_AREA
- addne r1, r2, #OFFSETOF_DISP_TRAP_AREA
- save_context r1, r3 // r1 = save_area
- mrc p15, 0, r0, c6, c0, 0 // r0 = fault address
- enter_sys r3
- b handle_user_page_fault // f(fault_addr, save_area)
-$dabt_kernel:
- // {r0-r3} spilled to stack
- sub r2, sp, #(NUM_REGS * 4) // Reserve stack space for save
- save_context r2, r3 // r2 = save_area
- mrc p15, 0, r1, c6, c0, 0 // r1 = fault address
- mov r0, #ARM_EVECTOR_DABT
- enter_sys r3
- b fatal_kernel_fault // f(evector, addr, save_area)
-
- //
- // void undef_handler(void)
- //
- // Entered in UNDEF mode, IRQ disabled, ARM state.
- //
- // NB Identical to PABT except for final jump in undef_user and
- // code doesn't adjust lr to point to faulting instruction since
- // it was undefined and there's no point re-executing it.
- //
-undef_handler:
- stmfd sp!, {r0-r3} // Save for scratch use
- mrs r3, spsr // r3 = spsr until save_context
- ands r1, r3, #ARM_MODE_PRIV
- bne $undef_kernel
-$undef_user:
- get_dispatcher_shared_arm r2
- sub r0, lr, #4 // r0 = faulting pc
- disp_is_disabled r2, r0, r1 // r1 = 1 if disabled, else 0
- cmp r1, #0
- addeq r1, r2, #OFFSETOF_DISP_ENABLED_AREA
- addne r1, r2, #OFFSETOF_DISP_TRAP_AREA
- save_context r1, r3 // r1 = save area
- enter_sys r3
- b handle_user_undef // f(fault_addr, save_area)
-$undef_kernel:
- sub r2, sp, #(NUM_REGS * 4) // Save to stack
- save_context r2, r3 // r2 = saved context
- sub r1, lr, #4 // r1 = fault address
- mov r0, #ARM_EVECTOR_UNDEF
- enter_sys r3
- bl fatal_kernel_fault // f(evector, addr, save_area)
-
- //
- // void irq_handler(void)
- //
- // Entered in IRQ mode, IRQ disabled, ARM state
- //
-irq_handler:
- stmfd sp!, {r0-r3} // Save for scratch use
- sub lr, lr, #4 // lr = return address
- mrs r3, spsr // r0 = spsr until save_context
- ands r1, r3, #ARM_MODE_PRIV
- bne $irq_kernel
-$irq_user:
- get_dispatcher_shared_arm r2
- mov r1, lr
- disp_is_disabled r2, r1, r0 // r0 = 1 if disabled, else 0
- cmp r0, #0
- addeq r0, r2, #OFFSETOF_DISP_ENABLED_AREA
- addne r0, r2, #OFFSETOF_DISP_DISABLED_AREA
- save_context r0, r3 // r0 = save area
- enter_sys r3
- mov lr, #0
- mov r11, #0
- b handle_irq // f(save_area, fault_pc)
-$irq_kernel:
- // CPU was in System mode.
- ldr r0, =irq_save_area
- save_context r0, r3 // r0 = saved context
- enter_sys r3
- b handle_irq // f(save_area)
-
- //
- // void swi_handler(void)
- //
- // Entered in SVC mode, IRQ disabled, ARM state.
- //
- // r0 = encoded syscall ordinal
- // r1 = syscall arg0
- // r2 = syscall arg1
- // ...
- // r7 = syscall arg6
- //
- // For now the system saves the caller's context here, because
- // some fraction of system calls do not return directly.
- //
-swi_handler:
- .if SYSCALL_REG <> 0
- .error "Syscall entry broken. Expected ordinal reg to be r0."
- .endif
-
- stmfd sp!, {r0-r3} // Save for scratch use
- mrs r3, spsr // r3 = spsr until save_context
- ands r1, r3, #ARM_MODE_PRIV
- bne $swi_kernel
-$swi_user:
- get_dispatcher_shared_arm r2
- disp_is_disabled r2, lr, r1 // r1 = 1 if disabled, else 0
- cmp r1, #0
- addeq r0, r2, #OFFSETOF_DISP_ENABLED_AREA
- addne r0, r2, #OFFSETOF_DISP_DISABLED_AREA
- save_context r0, r3 // r0 = save area, r3 = scratch
- enter_sys r3
- ldr r11, [r0, #48] // context->fp
- ldr lr, [r0, #60] // context->lr
- b sys_syscall
-
-$swi_kernel:
- b sys_syscall_kernel
+++ /dev/null
-/*
- * Copyright (c) 2009 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <init.h>
-#include <exceptions.h>
-#include <exec.h>
-#include <offsets.h>
-#include <paging_kernel_arch.h>
-#include <arch/armv5/phys_mmap.h>
-#include <serial.h>
-#include <stdio.h>
-#include <arm_hal.h>
-#include <cpiobin.h>
-#include <getopt/getopt.h>
-#include <kcb.h>
-
-//
-// ATAG boot header declarations
-//
-// See: http://www.simtec.co.uk/products/SWLINUX/files/booting_article.html
-//
-
-static const uint32_t ATAG_NONE = 0;
-static const uint32_t ATAG_CORE = 0x54410001;
-static const uint32_t ATAG_MEM = 0x54410002;
-static const uint32_t ATAG_VIDEOTEXT = 0x54410003;
-static const uint32_t ATAG_RAMDISK = 0x54410004;
-static const uint32_t ATAG_INITRD2 = 0x54420005;
-static const uint32_t ATAG_SERIAL = 0x54410006;
-static const uint32_t ATAG_REVISION = 0x54410007;
-static const uint32_t ATAG_VIDEOLFB = 0x54410008;
-static const uint32_t ATAG_CMDLINE = 0x54410009;
-
-struct atag_header {
- uint32_t size; // Size of header plus payload in 32-bit words
- uint32_t tag; // Payload identifier
-};
-
-struct atag_core {
- uint32_t flags; // bit 0 = r/o
- uint32_t page_bytes;
- uint32_t root_device;
-};
-
-struct atag_mem {
- uint32_t bytes;
- uint32_t start;
-};
-
-struct atag_videotext {
- uint8_t width;
- uint8_t height;
- uint16_t video_page;
- uint8_t video_mode;
- uint8_t video_cols;
- uint16_t video_ega_bx;
- uint8_t video_lines;
- uint8_t video_isvga;
- uint16_t video_points;
-};
-
-struct atag_ramdisk {
- uint32_t flags; // Bit 0 = load, bit 1 = prompt
- uint32_t bytes; // Decompressed size
- uint32_t start; // Starting block of RAM disk image
-};
-
-struct atag_initrd2 {
- uint32_t start; // Physical start address
- uint32_t bytes; // Copmressed disk image in bytes
-};
-
-struct atag_serial {
- uint32_t low; // Lower order bits of board serial number
- uint32_t high; // Upper order bits of board serial number
-};
-
-struct atag_revision {
- uint32_t board_revision;
-};
-
-struct atag_videolfb
-{
- uint16_t lfb_width;
- uint16_t lfb_height;
- uint16_t lfb_depth;
- uint16_t lfb_linelength;
- uint32_t lfb_base;
- uint32_t lfb_size;
- uint8_t red_size;
- uint8_t red_pos;
- uint8_t green_size;
- uint8_t green_pos;
- uint8_t bluint_te_size;
- uint8_t bluint_te_pos;
- uint8_t rsvd_size;
- uint8_t rsvd_pos;
-};
-
-struct atag_cmdline
-{
- char cmdline[1];
-};
-
-struct atag {
- struct atag_header header;
- union {
- struct atag_core core;
- struct atag_mem mem;
- struct atag_videotext videotext;
- struct atag_ramdisk ramdisk;
- struct atag_initrd2 initrd2;
- struct atag_serial serial;
- struct atag_revision revision;
- struct atag_videolfb videolfb;
- struct atag_cmdline cmdline;
- } u;
-};
-
-static struct atag * atag_find(struct atag *a, uint32_t tag)
-{
- while (a->header.tag != ATAG_NONE) {
- if (a->header.tag == tag) {
- return a;
- }
- a = (struct atag*)(a->header.size + (uint32_t*)a);
- }
- return NULL;
-}
-
-//
-// Macros used in command-line processing
-//
-
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#define CONSTRAIN(x, a, b) MIN(MAX(x, a), b)
-
-//
-// Kernel command line variables and binding options
-//
-
-static int tick_hz = 100;
-
-static struct cmdarg cmdargs[] = {
- { "consolePort", ArgType_UInt, { .uinteger = &serial_console_port}},
- { "debugPort", ArgType_UInt, { .uinteger = &serial_debug_port}},
- { "loglevel", ArgType_Int, { .integer = &kernel_loglevel }},
- { "logmask", ArgType_Int, { .integer = &kernel_log_subsystem_mask }},
- { "tickHz", ArgType_Int, { .integer = &tick_hz }},
- {NULL, 0, {NULL}}
-};
-
-/**
- * Entry point called from boot.S for bootstrap processor.
- */
-void arch_init(uint32_t board_id,
- struct atag *atag_base,
- lvaddr_t elf_file,
- lvaddr_t alloc_top)
-{
- //
- // Assumptions:
- //
- // - MMU and caches are enabled. No lockdowns in caches or TLB.
- // - Kernel has own section starting at KERNEL_OFFSET.
- // - Kernel section includes the highmem relocated exception vector table.
- //
-
-
- struct atag * ae = NULL;
-
- exceptions_init();
-
- ae = atag_find(atag_base, ATAG_MEM);
- paging_map_memory(0, ae->u.mem.start, ae->u.mem.bytes);
-
- ae = atag_find(atag_base, ATAG_CMDLINE);
- if (ae != NULL)
- {
- parse_commandline(ae->u.cmdline.cmdline, cmdargs);
- tick_hz = CONSTRAIN(tick_hz, 10, 1000);
- }
-
- if (board_id == hal_get_board_id())
- {
- errval_t errval;
-
- serial_console_init(true);
-
- // do not remove/change this printf: needed by regression harness
- printf("Barrelfish CPU driver starting on ARMv5 Board id 0x%08"PRIx32"\n",
- board_id);
- printf("The address of paging_map_kernel_section is %p\n",
- paging_map_kernel_section);
- errval = serial_debug_init();
- if (err_is_fail(errval))
- {
- printf("Failed to initialize debug port: %d", serial_debug_port);
- }
-
- debug(SUBSYS_STARTUP, "alloc_top %08"PRIxLVADDR" %08"PRIxLVADDR"\n",
- alloc_top, alloc_top - KERNEL_OFFSET);
- debug(SUBSYS_STARTUP, "elf_file %08"PRIxLVADDR"\n", elf_file);
-
- my_core_id = hal_get_cpu_id();
-
- pic_init();
- pit_init(tick_hz);
- tsc_init();
-
- ae = atag_find(atag_base, ATAG_MEM);
-
- // Add unused physical memory to memory map
-
- phys_mmap_t phys_mmap;
-
- // Kernel effectively consumes [0...alloc_top]
- // Add region above alloc_top with care to skip exception vector
- // page.
- if (alloc_top < ETABLE_ADDR) {
- phys_mmap_add(&phys_mmap,
- alloc_top - KERNEL_OFFSET,
- ETABLE_ADDR - KERNEL_OFFSET);
- }
-
- phys_mmap_add(&phys_mmap,
- ETABLE_ADDR - KERNEL_OFFSET + BASE_PAGE_SIZE,
- ae->u.mem.start + ae->u.mem.bytes);
-
- ae = atag_find(atag_base, ATAG_VIDEOLFB);
- if (NULL != ae)
- {
- // Remove frame buffer (if present).
- phys_mmap_remove(&phys_mmap,
- ae->u.videolfb.lfb_base,
- ae->u.videolfb.lfb_base + ae->u.videolfb.lfb_size);
- assert(!"Not supported");
- }
-
- ae = atag_find(atag_base, ATAG_INITRD2);
- if (NULL != ae)
- {
- phys_mmap_remove(&phys_mmap,
- ae->u.initrd2.start,
- ae->u.initrd2.start + ae->u.initrd2.bytes);
-
- arm_kernel_startup(&phys_mmap,
- ae->u.initrd2.start,
- ae->u.initrd2.bytes);
- }
- else {
- panic("initrd not found\n");
- }
- }
- else {
- panic("Mis-matched board id: [current %"PRIu32", kernel %"PRIu32"]",
- board_id, hal_get_board_id());
- }
-}
-
-struct kcb;
-errval_t irq_table_notify_domains(struct kcb *kcb)
-{
- return SYS_ERR_OK;
-}
+++ /dev/null
-/*
- * Copyright (c) 2007, 2009, ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <paging_kernel_arch.h>
-
-#include <dev/pl011_uart_dev.h>
-#include <dev/arm_icp_pic0_dev.h>
-#include <dev/arm_icp_pit_dev.h>
-
-#include <pl011_uart.h>
-#include <serial.h>
-#include <arm_hal.h>
-
-uint32_t hal_get_board_id(void)
-{
- return 0x113;
-}
-
-uint8_t hal_get_cpu_id(void)
-{
- return 0;
-}
-
-bool hal_cpu_is_bsp(void)
-{
- return true;
-}
-
-//
-// Interrupt controller
-//
-
-static arm_icp_pic0_source_un pic_primary_irqs;
-static arm_icp_pic0_t pic;
-
-void pic_init(void)
-{
- static const uintptr_t PIC_BASE = 0x14000000;
-
- arm_icp_pic0_source_t sources = {
- .SOFTINT = 1, .UARTINT0 = 1, .UARTINT1 = 1, .KBDINT = 1,
- .MOUSEINT = 1, .TIMERINT0 = 1, .TIMERINT1 = 1, .TIMERINT2 = 1,
- .RTCINT = 1, .LM_LLINT0 = 1, .LM_LLINT1 = 1, .CLCDCINT = 1,
- .MMCIINT0 = 1, .MMCIINT1 = 1, .AACIINT = 1, .CPPLDINT = 1,
- .ETH_INT = 1, .TS_PENINT = 1
- };
- pic_primary_irqs.val = sources;
-
- lvaddr_t pic_base = paging_map_device(PIC_BASE, 0x00100000);
- arm_icp_pic0_initialize(&pic, (mackerel_addr_t)pic_base);
-
- pic_disable_all_irqs();
-}
-
-void pic_set_irq_enabled(uint32_t irq, bool en)
-{
- uint32_t m = 1u << irq;
- if (irq < 32 && (pic_primary_irqs.raw & m) == m) {
- if (en) {
- m |= arm_icp_pic0_PIC_IRQ_ENABLESET_rd_raw(&pic);
- arm_icp_pic0_PIC_IRQ_ENABLESET_wr_raw(&pic, m);
- }
- else {
- arm_icp_pic0_PIC_IRQ_ENABLECLR_wr_raw(&pic, m);
- }
- }
- else {
- panic("Unknown IRQ source %"PRIu32, irq);
- }
-}
-
-void pic_disable_all_irqs(void)
-{
- arm_icp_pic0_PIC_IRQ_ENABLECLR_wr_raw(&pic, pic_primary_irqs.raw);
-}
-
-uint32_t pic_get_active_irq(void)
-{
- uint32_t status = arm_icp_pic0_PIC_IRQ_STATUS_rd_raw(&pic);
- uint32_t irq;
-
- for (irq = 0; irq < 32; irq++) {
- if (0 != (status & (1u << irq))) {
- return irq;
- }
- }
- return ~0ul;
-}
-
-void pic_ack_irq(uint32_t irq)
-{
- // From the ARM specs it looks as if just clearing the interrupt at the
- // peripheral will clear the interrupt. No explicit EOI.
-}
-
-//
-// Kernel timer and tsc
-//
-
-static const uintptr_t PIT_BASE = 0x13000000;
-static const uint32_t PIT_IRQ = 6;
-
-static arm_icp_pit_t pit;
-
-static lvaddr_t pit_map_resources(void)
-{
- static lvaddr_t timer_base = 0;
- if (timer_base == 0) {
- timer_base = paging_map_device(PIT_BASE, 0x100000);
- }
- return timer_base;
-}
-
-void pit_init(uint32_t tick_hz)
-{
- // PIT uses timer 1 (hardcoded to 1MHz)
- arm_icp_pit_LOAD_t load = { .value = 1000000 / tick_hz };
- arm_icp_pit_CONTROL_t control = {
- .oneshot = 0, .timer32 = 1, .prescale = arm_icp_pit_none,
- .int_enable = 0, .mode = arm_icp_pit_reload, .enable = 0
- };
-
- lvaddr_t timer_base = pit_map_resources();
-
- arm_icp_pit_initialize(&pit, (mackerel_addr_t)(timer_base + 0x100));
- arm_icp_pit_LOAD_wr(&pit, load);
- arm_icp_pit_CONTROL_wr(&pit, control);
-
- pic_set_irq_enabled(PIT_IRQ, 1);
-}
-
-void pit_start(void)
-{
- arm_icp_pit_CONTROL_t control = arm_icp_pit_CONTROL_rd(&pit);
- control.int_enable = 1;
- control.enable = 1;
- arm_icp_pit_CONTROL_wr(&pit, control);
-}
-
-bool pit_handle_irq(uint32_t irq)
-{
- if (PIT_IRQ == irq) {
- arm_icp_pit_INTCLR_wr_raw(&pit, ~0ul);
- return 1;
- }
- else {
- return 0;
- }
-}
-
-void pit_mask_irq(bool masked)
-{
- arm_icp_pit_CONTROL_t control = arm_icp_pit_CONTROL_rd(&pit);
- if (masked) {
- control.int_enable = 0;
- }
- else {
- control.int_enable = 1;
- }
- arm_icp_pit_CONTROL_wr(&pit, control);
-
- if (masked) {
- // Clear interrupt if pending.
- pit_handle_irq(PIT_IRQ);
- }
-}
-
-//
-// TSC uses timer 0 (assuming 40MHz for QEMU)
-//
-static const uint32_t tsc_hz = 40000000;
-static arm_icp_pit_t tsc;
-
-void tsc_init(void)
-{
- arm_icp_pit_LOAD_t load = { .value = ~0ul };
- arm_icp_pit_CONTROL_t control = {
- .oneshot = 0, .timer32 = 1, .prescale = arm_icp_pit_none,
- .int_enable = 0, .mode = arm_icp_pit_reload, .enable = 1
- };
- pit_map_resources();
-
- arm_icp_pit_initialize(&tsc, (mackerel_addr_t)pit_map_resources());
- arm_icp_pit_LOAD_wr(&tsc, load);
- arm_icp_pit_CONTROL_wr(&tsc, control);
-}
-
-uint32_t tsc_read(void)
-{
- // Timers count down so invert it.
- return ~arm_icp_pit_CURRENT_rd_raw(&tsc);
-}
-
-uint32_t tsc_get_hz(void)
-{
- return tsc_hz;
-}
-
-//
-// Serial console and debugger interfaces
-//
-
-#define NUM_PORTS 2
-unsigned serial_console_port = 0;
-unsigned serial_debug_port = 1;
-const unsigned serial_num_physical_ports = NUM_PORTS;
-
-
-#define UART0_VBASE 0xE0009000
-#define UART0_SECTION_OFFSET 0x9000
-#define UART_DEVICE_BYTES 0x4c
-#define UART_MAPPING_DIFF 0x1000
-
-static pl011_uart_t ports[NUM_PORTS];
-
-errval_t serial_init(unsigned port, bool hwinit)
-{
- if (port < NUM_PORTS) {
- assert(ports[port].base == 0);
-
- lvaddr_t base = paging_map_device(0x16000000ul + port * 0x01000000,
- 0x00100000);
-
- if (hwinit) {
- pl011_uart_init(&ports[port], base);
- }
- return SYS_ERR_OK;
- }
- else {
- return SYS_ERR_SERIAL_PORT_INVALID;
- }
-}
-errval_t serial_early_init(unsigned port)
-{
- return SYS_ERR_OK; // Unused
-}
-
-void serial_putchar(unsigned port, char c)
-{
- assert(port < NUM_PORTS);
- assert(ports[port].base != 0);
- pl011_putchar(&ports[port], c);
-};
-
-char serial_getchar(unsigned port)
-{
- assert(port < NUM_PORTS);
- assert(ports[port].base != 0);
- return pl011_getchar(&ports[port]);
-};
+++ /dev/null
-/*
- * Copyright (c) 2009 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <stdbool.h>
-
-extern void dbg_break(void);
-void dbg_break(void)
-{
- __asm("bkpt #0xffff");
-}
-
-extern void arch_benchmarks(void);
-void arch_benchmarks(void) { dbg_break(); }
-
-extern void arch_benchmarks_size(void);
-void arch_benchmarks_size(void) { dbg_break(); }
-
-extern void conio_putchar(void);
-void conio_putchar(void) { /* Don't break here yet! */ }
-
-extern void gdb_arch_continue(void);
-void gdb_arch_continue(void) { dbg_break(); }
-
-extern void gdb_arch_get_register(void);
-void gdb_arch_get_register(void) { dbg_break(); }
-
-extern void gdb_arch_read_byte(void);
-void gdb_arch_read_byte(void) { dbg_break(); }
-
-extern void gdb_arch_registers(void);
-void gdb_arch_registers(void) { dbg_break(); }
-
-extern void gdb_arch_set_register(void);
-void gdb_arch_set_register(void) { dbg_break(); }
-
-extern void gdb_arch_single_step(void);
-void gdb_arch_single_step(void) { dbg_break(); }
-
-extern void gdb_arch_write_byte(void);
-void gdb_arch_write_byte(void) { dbg_break(); }
-
-extern void reboot(void);
-void reboot(void) { dbg_break(); }
-
-struct dcb;
-extern void __attribute__ ((noreturn)) vmkit_vmenter (struct dcb *dcb);
-void vmkit_vmenter(struct dcb *dcb) { dbg_break(); for(;;); }
-
-extern void __aeabi_unwind_cpp_pr0(void);
-void __aeabi_unwind_cpp_pr0(void) { dbg_break(); }
-
-extern void raise(void);
-void raise(void) { dbg_break(); }
-
-extern void breakpoint(void);
-void breakpoint(void) { dbg_break(); }
-
-extern bool arch_core_is_bsp(void);
-bool arch_core_is_bsp(void) { return true; }
+++ /dev/null
-/*
- * Copyright (c) 2007, 2008, ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <offsets.h>
-
-OUTPUT_FORMAT("elf32-littlearm")
-OUTPUT_ARCH("arm")
-
-ENTRY(start)
-
-SECTIONS {
- . = START_KERNEL_PHYS + KERNEL_OFFSET;
- kernel_first_byte = .;
- .text : { *(.text); }
- kernel_text_final_byte = .;
-
- . = ALIGN(4k);
- .rodata . :
- {
- *(.rodata);
- }
-
- .got . :
- {
- got_base = .;
- *(.got);
- }
-
- .bss . :
- {
- *(.bss);
- }
-
- kernel_final_byte = .;
-
- /***** These sections get discarded *****/
- /DISCARD/ :
- {
- /* Discard exception handler frames and headers -- we don't use em */
- *(.eh_frame);
- *(.eh_frame_hdr);
- *(.note.gnu.build-id);
- *(.interp);
-/* *(.dynsym); */
-/* *(.dynstr); */
-/* *(.hash); */
-/* *(.gnu.hash); */
- *(.dynamic);
- }
-}
+++ /dev/null
-/*
- * Copyright (c) 2009 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <dispatch.h>
-#include <cp15.h>
-#include <paging_kernel_arch.h>
-#include <string.h>
-#include <cap_predicates.h>
-
-// ------------------------------------------------------------------------
-// Internal declarations
-
-union l1_entry {
- uint32_t raw;
-
- /// Invalid L1 entry
- struct {
- uint32_t type :2; // == 0
- } invalid;
-
- /// L1 entry for 256 4K L2 entries
- struct {
- uint32_t type :2; // == 1
- uint32_t sbz0 :2; // Should-be-zero
- uint32_t mb1 :1; // Must-be-one
- uint32_t domain :4;
- uint32_t sbz1 :1; // Should-be-zero
- uint32_t base_address :22;
- } coarse;
-
- /// L1 entry for 1MB mapped section
- struct {
- uint32_t type :2; // == 2
- uint32_t bufferable :1;
- uint32_t cacheable :1;
- uint32_t mb1 :1; // Must-be-One
- uint32_t domain :4;
- uint32_t sbz0 :1;
- uint32_t ap :2;
- uint32_t sbz1 :8;
- uint32_t base_address :12;
- } section;
-
- /// L1 entry for 1024 1K L2 descriptors
- struct {
- uint32_t type :2; // == 3
- uint32_t sbz0 :2;
- uint32_t mb1 :1;
- uint32_t domain :4;
- uint32_t sbz1 :3;
- uint32_t base_address :20;
- } fine;
-};
-
-STATIC_ASSERT_SIZEOF(union l1_entry, 4);
-
-#define L1_TYPE_INVALID_ENTRY 0
-#define L1_TYPE_COARSE_ENTRY 1
-#define L1_TYPE_SECTION_ENTRY 2
-#define L1_TYPE_FINE_ENTRY 3
-#define L1_TYPE(x) ((x) & 3)
-
-union l2_entry {
- uint32_t raw;
-
- /// Invalid L2 entry
- struct {
- uint32_t type :2; // == 0
- } invalid;
-
- /// Descriptior for a 64K page
- struct {
- uint32_t type :2; // == 1
- uint32_t bufferable :1;
- uint32_t cacheable :1;
- uint32_t ap0 :2;
- uint32_t ap1 :2;
- uint32_t ap2 :2;
- uint32_t ap3 :2;
- uint32_t sbz :4;
- uint32_t base_address :16;
- } large_page;
-
- /// Descriptor for a 4K page
- struct {
- uint32_t type :2; // == 2
- uint32_t bufferable :1;
- uint32_t cacheable :1;
- uint32_t ap0 :2;
- uint32_t ap1 :2;
- uint32_t ap2 :2;
- uint32_t ap3 :2;
- uint32_t base_address :20;
- } small_page;
-
- /// Descriptor for a 1K page
- struct {
- uint32_t type :2; // == 3
- uint32_t bufferable :1;
- uint32_t cacheable :1;
- uint32_t ap :2;
- uint32_t sbz :4;
- uint32_t base_address :22;
- } tiny_page;
-};
-
-STATIC_ASSERT_SIZEOF(union l2_entry, 4);
-
-#define L2_TYPE_INVALID_PAGE 0
-#define L2_TYPE_LARGE_PAGE 1
-#define L2_TYPE_SMALL_PAGE 2
-#define L2_TYPE_TINY_PAGE 3
-#define L2_TYPE(x) ((x) & 3)
-
-#define BYTES_PER_SECTION 0x100000
-#define BYTES_PER_PAGE 0x1000
-#define BYTES_PER_SMALL_PAGE 0x400
-
-// ------------------------------------------------------------------------
-// Utility declarations
-
-inline static uintptr_t paging_round_down(uintptr_t address, uintptr_t size)
-{
- return address & ~(size - 1);
-}
-
-inline static uintptr_t paging_round_up(uintptr_t address, uintptr_t size)
-{
- return (address + size - 1) & ~(size - 1);
-}
-
-inline static int aligned(uintptr_t address, uintptr_t bytes)
-{
- return (address & (bytes - 1)) == 0;
-}
-
-// ------------------------------------------------------------------------
-// Exported functions
-
-static void
-paging_write_section_entry(uintptr_t ttbase, lvaddr_t va, union l1_entry l1)
-{
- union l1_entry *l1_table;
- if (ttbase == 0) {
- ttbase = cp15_read_ttbr() + KERNEL_OFFSET;
- }
- l1_table = (union l1_entry *) ttbase;
- l1_table[va >> 20u] = l1;
-}
-
-void paging_map_kernel_section(uintptr_t ttbase, lvaddr_t va, lpaddr_t pa)
-{
-
- union l1_entry l1;
-
- l1.raw = 0;
- l1.section.type = L1_TYPE_SECTION_ENTRY;
- l1.section.bufferable = 1;
- l1.section.cacheable = 1;
- l1.section.ap = 1;
- l1.section.base_address = pa >> 20u;
-
- paging_write_section_entry(ttbase, va, l1);
-}
-
-void paging_map_memory(uintptr_t ttbase, lpaddr_t paddr, size_t bytes)
-{
- lpaddr_t pend = paging_round_up(paddr + bytes, BYTES_PER_SECTION);
- while (paddr < pend) {
- paging_map_kernel_section(0, paddr + MEMORY_OFFSET, paddr);
- paddr += BYTES_PER_SECTION;
- }
-}
-
-static void
-paging_map_device_section(uintptr_t ttbase, lvaddr_t va, lpaddr_t pa)
-{
- union l1_entry l1;
-
- l1.raw = 0;
- l1.section.type = L1_TYPE_SECTION_ENTRY;
- l1.section.bufferable = 0;
- l1.section.cacheable = 0;
- l1.section.ap = 1;
- l1.section.base_address = pa >> 20u;
-
- paging_write_section_entry(ttbase, va, l1);
-}
-
-lvaddr_t paging_map_device(lpaddr_t device_base, size_t device_bytes)
-{
- // HACK to put device in high memory.
- // Should likely track these allocations.
- static lvaddr_t dev_alloc = KERNEL_OFFSET;
- assert(device_bytes <= BYTES_PER_SECTION);
- dev_alloc -= BYTES_PER_SECTION;
-
- paging_map_device_section(0, dev_alloc, device_base);
-
- return dev_alloc;
-}
-
-void paging_make_good(lvaddr_t new_table_base, size_t new_table_bytes)
-{
- assert(new_table_base >= MEMORY_OFFSET);
- assert(new_table_bytes == ARM_L1_ALIGN);
- assert(aligned(new_table_base, ARM_L1_ALIGN));
-
- lvaddr_t ttbr = local_phys_to_mem(cp15_read_ttbr());
- size_t st = (MEMORY_OFFSET / ARM_L1_SECTION_BYTES) * ARM_L1_BYTES_PER_ENTRY;
-
- // Copy kernel pages (everything from MEMORY_OFFSET upwards)
- memcpy((void*)new_table_base + st, (void*)ttbr + st,
- ARM_L1_MAX_ENTRIES * ARM_L1_BYTES_PER_ENTRY - st);
-}
-
-void paging_map_user_pages_l1(lvaddr_t table_base, lvaddr_t va, lpaddr_t pa)
-{
- assert(aligned(table_base, ARM_L1_ALIGN));
- assert(aligned(va, BYTES_PER_SECTION));
- assert(aligned(pa, BYTES_PER_SMALL_PAGE));
-
- union l1_entry e;
-
- e.raw = 0;
- e.coarse.type = L1_TYPE_COARSE_ENTRY;
- e.coarse.mb1 = 1;
- e.coarse.domain = 0;
- e.coarse.base_address = (pa >> 10);
-
- union l1_entry *l1table = (union l1_entry*)table_base;
- l1table[va / BYTES_PER_SECTION] = e;
-}
-
-void paging_set_l2_entry(uintptr_t* l2e, lpaddr_t addr, uintptr_t flags)
-{
- assert(0 == (flags & 0xfffff000));
- assert(0 == (flags & 0x3));
- assert(0 == (addr & 0xfff));
-
- union l2_entry e;
- e.raw = flags;
- assert(e.small_page.ap0 == e.small_page.ap1 &&
- e.small_page.ap0 == e.small_page.ap2 &&
- e.small_page.ap0 == e.small_page.ap3);
-
- e.small_page.type = L2_TYPE_SMALL_PAGE;
- e.small_page.base_address = (addr >> 12);
-
- *l2e = e.raw;
-}
-
-void paging_context_switch(lpaddr_t ttbr)
-{
- assert(ttbr < MEMORY_OFFSET);
- assert((ttbr & 0x3fff) == 0);
-
- lpaddr_t old_ttbr = cp15_read_ttbr();
- if (ttbr != old_ttbr)
- {
- cp15_write_ttbr(ttbr);
- cp15_invalidate_tlb();
- cp15_invalidate_i_and_d_caches();
- }
-}
-
-static void
-paging_set_flags(union l2_entry *entry, uintptr_t kpi_paging_flags)
-{
- entry->small_page.bufferable = 1;
- entry->small_page.cacheable =
- (kpi_paging_flags & KPI_PAGING_FLAGS_NOCACHE) ? 0 : 1;
-
- entry->small_page.ap0 =
- (kpi_paging_flags & KPI_PAGING_FLAGS_READ) ? 2 : 0;
- entry->small_page.ap0 |=
- (kpi_paging_flags & KPI_PAGING_FLAGS_WRITE) ? 3 : 0;
- entry->small_page.ap1 = entry->small_page.ap0;
- entry->small_page.ap2 = entry->small_page.ap0;
- entry->small_page.ap3 = entry->small_page.ap0;
-}
-
-static errval_t
-caps_map_l1(struct capability* dest,
- cslot_t slot,
- struct capability* src,
- uintptr_t kpi_paging_flags,
- uintptr_t offset,
- uintptr_t pte_count)
-{
- //
- // Note:
- //
- // We have chicken-and-egg problem in initializing resources so
- // instead of treating an L2 table it's actual 1K size, we treat
- // it as being 4K. As a result when we map an "L2" table we actually
- // map a page of memory as if it is 4 consecutive L2 tables.
- //
- // See lib/barrelfish/arch/arm/pmap_arch.c for more discussion.
- //
- // XXX: magic constant
- const int ARM_L1_SCALE = 4;
-
- if (slot >= 4096) {
- printf("Error: slot = %"PRIuCSLOT"\n",slot);
- return SYS_ERR_VNODE_SLOT_INVALID;
- }
-
- // check offset within frame
- if ((offset + pte_count * 1024 > get_size(src)) ||
- ((offset % 1024) != 0)) {
- printf("Error: offset = %"PRIuPTR", pte_count=%"PRIuPTR
- ", src->size = %"PRIuGENSIZE", src->type = %d\n",
- offset, pte_count, get_size(src), src->type);
- return SYS_ERR_FRAME_OFFSET_INVALID;
- }
-
- // check mapping does not overlap leaf page table
- if (slot + pte_count > 4096) {
- return SYS_ERR_VM_MAP_SIZE;
- }
-
-
- if (slot >= ARM_L1_OFFSET(MEMORY_OFFSET)) {
- printf("slot = %"PRIuCSLOT"\n",slot);
- return SYS_ERR_VNODE_SLOT_RESERVED;
- }
-
- debug(SUBSYS_PAGING, "caps_map_l1: mapping %"PRIuPTR" L2 tables @%"PRIuCSLOT"\n",
- pte_count, slot);
- // Destination
- lpaddr_t dest_lpaddr = gen_phys_to_local_phys(get_address(dest));
- lvaddr_t dest_lvaddr = local_phys_to_mem(dest_lpaddr);
-
- union l1_entry* entry = (union l1_entry*)dest_lvaddr + slot;
-
- // Source
- genpaddr_t src_gpaddr = get_address(src);
- lpaddr_t src_lpaddr = gen_phys_to_local_phys(src_gpaddr) + offset;
-
- assert(aligned(src_lpaddr, 1u << 10));
- assert((src_lpaddr < dest_lpaddr) || (src_lpaddr >= dest_lpaddr + 16384));
-
- struct cte *src_cte = cte_for_cap(src);
- src_cte->mapping_info.pte_count = pte_count;
- src_cte->mapping_info.pte = dest_lpaddr + slot;
- src_cte->mapping_info.offset = 0;
-
- for (int i = 0; i < pte_count; i++, entry++)
- {
-
- entry->raw = 0;
- entry->coarse.type = L1_TYPE_COARSE_ENTRY;
- entry->coarse.mb1 = 1;
- entry->coarse.domain = 0;
- entry->coarse.base_address =
- (src_lpaddr + i * BASE_PAGE_SIZE / ARM_L1_SCALE) >> 10;
- debug(SUBSYS_PAGING, "L1 mapping %"PRIuCSLOT". @%p = %08"PRIx32"\n",
- slot + i, entry, entry->raw);
- }
-
- cp15_invalidate_tlb();
-
- return SYS_ERR_OK;
-}
-
-static errval_t
-caps_map_l2(struct capability* dest,
- cslot_t slot,
- struct capability* src,
- uintptr_t kpi_paging_flags,
- uintptr_t offset,
- uintptr_t pte_count)
-{
- assert(0 == (kpi_paging_flags & ~KPI_PAGING_FLAGS_MASK));
-
- // ARM L2 has 256 entries, but we treat a 4K page as a consecutive
- // region of L2 with a single index. 4K == 4 * 1K
- if (slot >= (256 * 4)) {
- panic("oops");
- return SYS_ERR_VNODE_SLOT_INVALID;
- }
-
- if (src->type != ObjType_Frame && src->type != ObjType_DevFrame) {
- panic("oops");
- return SYS_ERR_WRONG_MAPPING;
- }
-
- // check offset within frame
- if ((offset + BYTES_PER_PAGE > get_size(src)) ||
- ((offset % BYTES_PER_PAGE) != 0)) {
- panic("oops");
- return SYS_ERR_FRAME_OFFSET_INVALID;
- }
-
- // check mapping does not overlap leaf page table
- if (slot + pte_count > (256 * 4)) {
- return SYS_ERR_VM_MAP_SIZE;
- }
-
- // Destination
- lpaddr_t dest_lpaddr = gen_phys_to_local_phys(get_address(dest));
- lvaddr_t dest_lvaddr = local_phys_to_mem(dest_lpaddr);
-
- union l2_entry* entry = (union l2_entry*)dest_lvaddr + slot;
- if (entry->small_page.type != L2_TYPE_INVALID_PAGE) {
- panic("Remapping valid page.");
- }
-
- lpaddr_t src_lpaddr = gen_phys_to_local_phys(get_address(src) + offset);
- if ((src_lpaddr & (BASE_PAGE_SIZE - 1))) {
- panic("Invalid target");
- }
-
- struct cte *src_cte = cte_for_cap(src);
- src_cte->mapping_info.pte_count = pte_count;
- src_cte->mapping_info.pte = dest_lpaddr;
- src_cte->mapping_info.offset = offset;
-
- for (int i = 0; i < pte_count; i++) {
- entry->raw = 0;
-
- entry->small_page.type = L2_TYPE_SMALL_PAGE;
- paging_set_flags(entry, kpi_paging_flags);
- entry->small_page.base_address = (src_lpaddr + i * BYTES_PER_PAGE) >> 12;
-
- entry++;
-
- debug(SUBSYS_PAGING, "L2 mapping %08"PRIxLVADDR"[%"PRIuCSLOT"] @%p = %08"PRIx32"\n",
- dest_lvaddr, slot, entry, entry->raw);
- }
-
- // Flush TLB if remapping.
- cp15_invalidate_tlb();
-
- return SYS_ERR_OK;
-}
-
-/// Create page mappings
-errval_t caps_copy_to_vnode(struct cte *dest_vnode_cte, cslot_t dest_slot,
- struct cte *src_cte, uintptr_t flags,
- uintptr_t offset, uintptr_t pte_count)
-{
- struct capability *src_cap = &src_cte->cap;
- struct capability *dest_cap = &dest_vnode_cte->cap;
-
- if (src_cte->mapping_info.pte) {
- return SYS_ERR_VM_ALREADY_MAPPED;
- }
-
-
- if (ObjType_VNode_ARM_l1 == dest_cap->type) {
- //printf("caps_map_l1: %zu\n", (size_t)pte_count);
- return caps_map_l1(dest_cap, dest_slot, src_cap,
- flags,
- offset,
- pte_count
- );
- }
- else if (ObjType_VNode_ARM_l2 == dest_cap->type) {
- //printf("caps_map_l2: %zu\n", (size_t)pte_count);
- return caps_map_l2(dest_cap, dest_slot, src_cap,
- flags,
- offset,
- pte_count
- );
- }
- else {
- panic("ObjType not VNode");
- }
-}
-
-size_t do_unmap(lvaddr_t pt, cslot_t slot, size_t num_pages)
-{
- size_t unmapped_pages = 0;
- union l2_entry *ptentry = (union l2_entry *)pt + slot;
- for (int i = 0; i < num_pages; i++) {
- ptentry++->raw = 0;
- unmapped_pages++;
- }
- return unmapped_pages;
-}
-
-static inline void read_pt_entry(struct capability *pgtable, size_t slot, genpaddr_t *paddr)
-{
- assert(type_is_vnode(pgtable->type));
- assert(paddr);
-
- genpaddr_t gp = get_address(pgtable);
- lpaddr_t lp = gen_phys_to_local_phys(gp);
- lvaddr_t lv = local_phys_to_mem(lp);
-
- switch (pgtable->type) {
- case ObjType_VNode_ARM_l1:
- {
- union l1_entry *e = (union l1_entry*)lv;
- *paddr = (genpaddr_t)(e->coarse.base_address) << 10;
- return;
- }
- case ObjType_VNode_ARM_l2:
- {
- union l2_entry *e = (union l2_entry*)lv;
- *paddr = (genpaddr_t)(e->small_page.base_address) << 12;
- return;
- }
- default:
- assert(!"Should not get here");
- }
-}
-
-errval_t page_mappings_unmap(struct capability *pgtable, struct cte *mapping, size_t slot, size_t num_pages)
-{
- assert(type_is_vnode(pgtable->type));
- //printf("page_mappings_unmap(%zd pages, slot = %zd)\n", num_pages, slot);
-
- // get page table entry data
- genpaddr_t paddr;
- //lpaddr_t pte;
- read_pt_entry(pgtable, slot, &paddr);
- lvaddr_t pt = local_phys_to_mem(gen_phys_to_local_phys(get_address(pgtable)));
-
- // get virtual address of first page
- // TODO: error checking
- genvaddr_t vaddr;
- struct cte *leaf_pt = cte_for_cap(pgtable);
- compile_vaddr(leaf_pt, slot, &vaddr);
- //genvaddr_t vend = vaddr + num_pages * BASE_PAGE_SIZE;
- // printf("vaddr = 0x%"PRIxGENVADDR"\n", vaddr);
- // printf("num_pages = %zu\n", num_pages);
-
- // get cap for mapping
- /*
- struct cte *mem;
- errval_t err = lookup_cap_for_mapping(paddr, pte, &mem);
- if (err_is_fail(err)) {
- printf("page_mappings_unmap: %ld\n", err);
- return err;
- }
- */
- //printf("state before unmap: mapped_pages = %zd\n", mem->mapping_info.mapped_pages);
- //printf("state before unmap: num_pages = %zd\n", num_pages);
-
- if (num_pages != mapping->mapping_info.pte_count) {
- printf("num_pages = %zu, mapping = %zu\n", num_pages, mapping->mapping_info.pte_count);
- // want to unmap a different amount of pages than was mapped
- return SYS_ERR_VM_MAP_SIZE;
- }
-
- do_unmap(pt, slot, num_pages);
-
- // flush TLB for unmapped pages
- // TODO: selective TLB flush
- cp15_invalidate_tlb();
-
- // update mapping info
- memset(&mapping->mapping_info, 0, sizeof(struct mapping_info));
-
- return SYS_ERR_OK;
-}
-
-errval_t paging_modify_flags(struct capability *frame, uintptr_t offset,
- uintptr_t pages, uintptr_t kpi_paging_flags)
-{
- // check flags
- assert(0 == (kpi_paging_flags & ~KPI_PAGING_FLAGS_MASK));
-
- struct cte *mapping = cte_for_cap(frame);
- struct mapping_info *info = &mapping->mapping_info;
-
- /* Calculate location of page table entries we need to modify */
- lvaddr_t base = local_phys_to_mem(info->pte) + offset;
-
- for (int i = 0; i < pages; i++) {
- union l2_entry *entry =
- (union l2_entry *)base + i;
- paging_set_flags(entry, kpi_paging_flags);
- }
-
- return paging_tlb_flush_range(mapping, offset, pages);
-}
-
-void paging_dump_tables(struct dcb *dispatcher)
-{
- lvaddr_t l1 = local_phys_to_mem(dispatcher->vspace);
-
- for (int l1_index = 0; l1_index < ARM_L1_MAX_ENTRIES; l1_index++) {
- // get level2 table
- union l1_entry *l2 = ((union l1_entry *)l1) + l1_index;
- if (L1_TYPE(l2->raw) == L1_TYPE_INVALID_ENTRY) { continue; }
-
- if (L1_TYPE(l2->raw) == L1_TYPE_SECTION_ENTRY) {
- genpaddr_t paddr = ((genpaddr_t)l2->section.base_address) << 20u;
- printf("%d: 0x%"PRIxGENPADDR"\n", l1_index, paddr);
- continue;
- }
-
- else if (L1_TYPE(l2->raw) != L1_TYPE_COARSE_ENTRY) {
- printf("%d: 0x%"PRIx32" -> type = %d not handled\n", l1_index, l2->raw, L1_TYPE(l2->raw));
- continue;
- }
-
- genpaddr_t ptable_gp = (genpaddr_t)(l2->coarse.base_address) << 10;
- lvaddr_t ptable_lv = local_phys_to_mem(gen_phys_to_local_phys(ptable_gp));
-
- for (int entry = 0; entry < ARM_L2_MAX_ENTRIES; entry++) {
- union l2_entry *e =
- (union l2_entry *)ptable_lv + entry;
- genpaddr_t paddr = (genpaddr_t)(e->small_page.base_address) << BASE_PAGE_BITS;
- if (!paddr) {
- continue;
- }
- printf("%d.%d: 0x%"PRIxGENPADDR"\n", l1_index, entry, paddr);
- }
- }
-}
+++ /dev/null
-/**
- * \file
- * \brief Rudimentary physical memory map implementation.
- */
-/* XXX - why is this rudimentary? */
-/* XXX - why is this in ARM-specific code? */
-
-/*
- * Copyright (c) 2008, 2010, ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <assert.h>
-#include <stddef.h>
-#include <barrelfish_kpi/types.h>
-#include <arch/armv5/phys_mmap.h>
-
-#include <stdio.h>
-
-static void phys_mmap_push(phys_mmap_t* mmap,
- int index,
- phys_region_t *region)
-{
- assert(index <= mmap->region_count &&
- mmap->region_count < PHYS_MAX_REGIONS - 1);
- for (int i = mmap->region_count; i > index; i--)
- {
- mmap->regions[i] = mmap->regions[i - 1];
- }
- mmap->regions[index] = *region;
- mmap->region_count++;
-}
-
-static void phys_mmap_pop(phys_mmap_t* mmap,
- int index)
-{
- assert(index < mmap->region_count &&
- mmap->region_count < PHYS_MAX_REGIONS);
- for (int i = index; i < mmap->region_count - 1; i++)
- {
- mmap->regions[i] = mmap->regions[i + 1];
- }
- mmap->region_count--;
-}
-
-int phys_mmap_add(phys_mmap_t* mmap,
- lpaddr_t start,
- lpaddr_t limit)
-{
- phys_region_t n = { start, limit };
-
- assert(limit > start);
-
- for (int i = 0; i < mmap->region_count; i++)
- {
- if (limit <= mmap->regions[i].start)
- {
- assert(i == 0 || start >= mmap->regions[i - 1].limit);
- phys_mmap_push(mmap, i, &n);
- return 1;
- }
- assert(start >= mmap->regions[i].limit);
- }
-
- assert(mmap->region_count == 0 ||
- start >= mmap->regions[mmap->region_count - 1].limit);
- phys_mmap_push(mmap, mmap->region_count, &n);
-
- return 1;
-}
-
-lpaddr_t phys_mmap_alloc(phys_mmap_t* mmap,
- size_t bytes,
- size_t align)
-{
- int i = 0;
-
- assert(0 == (align & (align - 1)));
- align -= 1;
-
- for (i = 0; i < mmap->region_count; i++)
- {
- phys_region_t* r = &mmap->regions[i];
- lpaddr_t alloc = (r->start + align) & ~align;
- size_t space = (r->limit > alloc) ? (r->limit - alloc) : 0;
- if (space < bytes)
- {
- continue;
- }
- else if ((alloc + bytes) == r->limit)
- {
- // end of allocation matches end of region
- if (alloc == r->start)
- {
- // completely consuming region
- phys_mmap_pop(mmap, i);
- return alloc;
- }
- else if (alloc > r->start)
- {
- // consuming end of region
- r->limit -= bytes;
- return alloc;
- }
- }
- else if (alloc == r->start)
- {
- // consuming start of region
- r->start = alloc + bytes;
- return alloc;
- }
- else if ((alloc + bytes) < mmap->regions[i].limit)
- {
- // consuming middle of region
- phys_mmap_push(mmap, i, r);
- r->limit = alloc;
- mmap->regions[i + 1].start = alloc + bytes;
- return alloc;
- }
- }
- return 0;
-}
-
-void phys_mmap_remove(phys_mmap_t* mmap,
- lpaddr_t start,
- lpaddr_t limit)
-{
- assert(limit > start);
-
- for (int i = mmap->region_count - 1; i >= 0; i--)
- {
- if (start >= mmap->regions[i].limit)
- {
- break;
- }
- else if (limit <= mmap->regions[i].start)
- {
- continue;
- }
- else if (start <= mmap->regions[i].start)
- {
- if (limit >= mmap->regions[i].limit)
- {
- // region i is subsumed
- phys_mmap_pop(mmap, i);
- }
- else
- {
- // region i is truncated
- mmap->regions[i].start = limit;
- assert(mmap->regions[i].start < mmap->regions[i].limit);
- }
- }
- else if (limit >= mmap->regions[i].limit)
- {
- // region i limit is truncated
- mmap->regions[i].limit = start;
- break;
- }
- else
- {
- // region i is sliced in two
- phys_region_t n = { limit, mmap->regions[i].limit };
-
- assert(start > mmap->regions[i].start &&
- limit < mmap->regions[i].limit);
- mmap->regions[i].limit = start;
- phys_mmap_push(mmap, i + 1, &n);
- break;
- }
- }
-}
-
+++ /dev/null
-/**
- * \file
- * \brief The world's simplest serial driver.
- */
-
-/*
- * Copyright (c) 2007, 2008, ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <arm.h>
-
-#include <dev/pl011_uart_dev.h>
-#include <pl011_uart.h>
-
-void pl011_uart_init(pl011_uart_t *uart, lvaddr_t base)
-{
- pl011_uart_LCR_H_t lcr = {
- .brk = 0, .pen = 0, .eps = 0, .stp2 = 0, .fen = 1,
- .wlen = pl011_uart_bits8, .sps = 0
- };
-
- pl011_uart_initialize(uart, (mackerel_addr_t) base);
-
- // Mask all interrupts
- pl011_uart_IMSC_wr_raw(uart, ~0ul);
-
- // Configure port to 38400 baud, 8 data, no parity, 1 stop (8-N-1)
- //
- // (This is a mild scam as system is running in QEMU)
- //
- // Note baud rate changes not committed in h/w until lcr_h written.
-
- pl011_uart_IBRD_wr_raw(uart, 0xc); // Assuming UARTCLK is 7.3728MHz
- pl011_uart_FBRD_wr_raw(uart, 0);
-
- pl011_uart_LCR_H_wr(uart, lcr);
-}
-
-/** \brief Prints a single character to the default serial port. */
-void pl011_putchar(pl011_uart_t *uart, char c)
-{
- pl011_uart_DR_un dr_un;
-
- while (pl011_uart_FR_rd(uart).txff == 1)
- ;
-
- dr_un.raw = 0;
- dr_un.val.data = (uint8_t)c;
- pl011_uart_DR_wr(uart, dr_un.val);
-}
-
-/** \brief Reads a single character from the default serial port.
- * This function spins waiting for a character to arrive.
- */
-char pl011_getchar(pl011_uart_t *uart)
-{
- while (pl011_uart_FR_rd(uart).rxfe == 1)
- ;
-
- return (char) pl011_uart_DR_rd(uart).data;
-}
+++ /dev/null
-/*
- * Copyright (c) 2009, 2010 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <dispatch.h>
-#include <string.h>
-#include <stdio.h>
-
-#include <barrelfish_kpi/init.h>
-#include <barrelfish_kpi/syscalls.h>
-#include <elf/elf.h>
-
-#include <arm_hal.h>
-#include <paging_kernel_arch.h>
-#include <exceptions.h>
-#include <cp15.h>
-#include <cpiobin.h>
-#include <init.h>
-#include <arch/armv5/phys_mmap.h>
-#include <barrelfish_kpi/paging_arm_v5.h>
-#include <startup.h>
-#include <kcb.h>
-
-#ifdef __XSCALE__
-#include <romfs_size.h>
-#endif
-
-#define CNODE(cte) (cte)->cap.u.cnode.cnode
-#define UNUSED(x) (x) = (x)
-
-#define STARTUP_PROGRESS() debug(SUBSYS_STARTUP, "%s:%d\n", \
- __FUNCTION__, __LINE__);
-
-#define BSP_INIT_MODULE_NAME BF_BINARY_PREFIX "armv5/sbin/init"
-
-#define INIT_L1_BYTES (ARM_L1_MAX_ENTRIES * ARM_L1_BYTES_PER_ENTRY)
-
-#define INIT_L2_PAGES ((INIT_SPACE_LIMIT - INIT_VBASE) / BASE_PAGE_SIZE)
-#define INIT_L2_BYTES INIT_L2_PAGES * ARM_L2_BYTES_PER_ENTRY
-
-#define INIT_BOOTINFO_VBASE INIT_VBASE
-#define INIT_ARGS_VBASE (INIT_BOOTINFO_VBASE + BOOTINFO_SIZE)
-#define INIT_DISPATCHER_VBASE (INIT_ARGS_VBASE + ARGS_SIZE)
-
-#define INIT_PERM_RO (ARM_L2_SMALL_CACHEABLE | \
- ARM_L2_SMALL_BUFFERABLE | \
- ARM_L2_SMALL_USR_RO)
-
-#define INIT_PERM_RW (ARM_L2_SMALL_CACHEABLE | \
- ARM_L2_SMALL_BUFFERABLE | \
- ARM_L2_SMALL_USR_RW)
-
-static phys_mmap_t* g_phys_mmap; // Physical memory map
-static uintptr_t* init_l1; // L1 page table for init
-static uintptr_t* init_l2; // L2 page tables for init
-
-static struct spawn_state spawn_state;
-
-static inline uintptr_t round_up(uintptr_t value, size_t unit)
-{
- assert(0 == (unit & (unit - 1)));
- size_t m = unit - 1;
- return (value + m) & ~m;
-}
-
-static inline uintptr_t round_down(uintptr_t value, size_t unit)
-{
- assert(0 == (unit & (unit - 1)));
- size_t m = unit - 1;
- return value & ~m;
-}
-
-static lpaddr_t alloc_phys_aligned(size_t bytes, size_t align)
-{
- bytes = round_up(bytes, align);
- lpaddr_t a = phys_mmap_alloc(g_phys_mmap, bytes, align);
- assert(0 == (a & (align - 1)));
- return a;
-}
-
-static lpaddr_t alloc_phys(size_t bytes)
-{
- return alloc_phys_aligned(bytes, BASE_PAGE_SIZE);
-}
-
-static lvaddr_t alloc_mem_aligned(size_t bytes, size_t align)
-{
- return local_phys_to_mem(alloc_phys_aligned(bytes, align));
-}
-
-static lvaddr_t alloc_mem(size_t bytes)
-{
- return local_phys_to_mem(alloc_phys_aligned(bytes, BASE_PAGE_SIZE));
-}
-
-/**
- * Map frames into init process address space. Init has a contiguous set of
- * l2 entries so this is straightforward.
- *
- * @param l2_table pointer to init's L2 table.
- * @param l2_base virtual address represented by first L2 table entry
- * @param va_base virtual address to map.
- * @param pa_base physical address to associate with virtual address.
- * @param bytes number of bytes to map.
- * @param l2_flags ARM L2 small page flags for mapped pages.
- */
-static void
-spawn_init_map(uintptr_t* l2_table,
- lvaddr_t l2_base,
- lvaddr_t va_base,
- lpaddr_t pa_base,
- size_t bytes,
- uintptr_t l2_flags)
-{
- assert(va_base >= l2_base);
- assert(0 == (va_base & (BASE_PAGE_SIZE - 1)));
- assert(0 == (pa_base & (BASE_PAGE_SIZE - 1)));
- assert(0 == (bytes & (BASE_PAGE_SIZE - 1)));
-
- int bi = (va_base - l2_base) / BASE_PAGE_SIZE;
- int li = bi + bytes / BASE_PAGE_SIZE;
-
- while (bi < li)
- {
- paging_set_l2_entry(&l2_table[bi], pa_base, l2_flags);
- pa_base += BASE_PAGE_SIZE;
- bi++;
- }
-}
-
-static uint32_t elf_to_l2_flags(uint32_t eflags)
-{
- switch (eflags & (PF_W|PF_R))
- {
- case PF_W|PF_R:
- return (ARM_L2_SMALL_USR_RW |
- ARM_L2_SMALL_CACHEABLE |
- ARM_L2_SMALL_BUFFERABLE);
- case PF_R:
- return (ARM_L2_SMALL_USR_RO |
- ARM_L2_SMALL_CACHEABLE |
- ARM_L2_SMALL_BUFFERABLE);
- default:
- panic("Unknown ELF flags combination.");
- }
-}
-
-struct startup_l2_info
-{
- uintptr_t* l2_table;
- lvaddr_t l2_base;
-};
-
-static errval_t
-startup_alloc_init(
- void* state,
- genvaddr_t gvbase,
- size_t bytes,
- uint32_t flags,
- void** ret
- )
-{
- const struct startup_l2_info* s2i = (const struct startup_l2_info*)state;
-
- lvaddr_t sv = round_down((lvaddr_t)gvbase, BASE_PAGE_SIZE);
- size_t off = (lvaddr_t)gvbase - sv;
- lvaddr_t lv = round_up((lvaddr_t)gvbase + bytes, BASE_PAGE_SIZE);
- lpaddr_t pa;
-
- STARTUP_PROGRESS();
- if (lv > sv && ((pa = alloc_phys(lv - sv)) != 0))
- {
- spawn_init_map(s2i->l2_table, s2i->l2_base, sv,
- pa, lv - sv, elf_to_l2_flags(flags));
- *ret = (void*)(local_phys_to_mem(pa) + off);
- }
- else
- {
- *ret = 0;
- }
- return SYS_ERR_OK;
-}
-
-static void
-load_init_image(
- struct startup_l2_info* l2i,
- const uint8_t* initrd_base,
- size_t initrd_bytes,
- genvaddr_t* init_ep,
- genvaddr_t* got_base
- )
-{
- const uint8_t* elf_base;
- size_t elf_bytes;
- int found;
-
- STARTUP_PROGRESS();
- *init_ep = *got_base = 0;
-
- found = cpio_get_file_by_name(initrd_base,
- initrd_bytes,
- BSP_INIT_MODULE_NAME,
- &elf_base, &elf_bytes);
- if (!found)
- {
- panic("Failed to find " BSP_INIT_MODULE_NAME "\n");
- }
-
- debug(SUBSYS_STARTUP, "load_init_image %p %08x\n", initrd_base, initrd_bytes);
-
- errval_t err = elf_load(EM_ARM, startup_alloc_init, l2i,
- (lvaddr_t)elf_base, elf_bytes, init_ep);
- if (err_is_fail(err))
- {
- panic("ELF load of " BSP_INIT_MODULE_NAME " failed!\n");
- }
-
- // TODO: Fix application linkage so that it's non-PIC.
- struct Elf32_Shdr* got_shdr =
- elf32_find_section_header_name((lvaddr_t)elf_base, elf_bytes, ".got");
- if (got_shdr)
- {
- *got_base = got_shdr->sh_addr;
- }
-}
-
-static void
-create_modules_from_initrd(struct bootinfo* bi,
- const uint8_t* initrd_base,
- size_t initrd_bytes)
-{
- errval_t err;
- lvaddr_t mmstrings_base = 0;
- lvaddr_t mmstrings = 0;
-
- // CPIO archive is crafted such that first file is
- // command-line strings for "modules" - ie menu.lst. The
- // subsequent file follow in the order they appear in
- // menu.lst.arm.
- const uint8_t* data;
- size_t bytes;
-
- if (cpio_get_file_by_name(initrd_base, initrd_bytes,
- "menu.lst.modules",
- &data, &bytes))
- {
- assert(bytes < BASE_PAGE_SIZE);
-
- mmstrings_base = alloc_mem(BASE_PAGE_SIZE);
- mmstrings = mmstrings_base;
-
- STARTUP_PROGRESS();
-
- // Create cap for strings area in first slot of modulecn
- err = caps_create_new(
- ObjType_Frame,
- mem_to_local_phys(mmstrings_base),
- BASE_PAGE_BITS, BASE_PAGE_BITS,
- my_core_id,
- caps_locate_slot(
- CNODE(spawn_state.modulecn),
- spawn_state.modulecn_slot++)
- );
- assert(err_is_ok(err));
-
- STARTUP_PROGRESS();
-
- // Copy strings from file into allocated page
- memcpy((void*)mmstrings_base, data, bytes);
- ((char*)mmstrings_base)[bytes] = '\0';
-
- STARTUP_PROGRESS();
-
- // Skip first line (corresponds to bootscript in archive)
- strtok((char*)mmstrings_base, "\r\n");
-
- STARTUP_PROGRESS();
-
- assert(bi->regions_length == 0);
- int ord = 1;
- const char* name;
- while ((mmstrings = (lvaddr_t)strtok(NULL, "\r\n")) != 0)
- {
- if (!cpio_get_file_by_ordinal(initrd_base, initrd_bytes, ord,
- &name, &data, &bytes))
- {
- panic("Failed to find file\n");
- }
- ord++;
-
- debug(SUBSYS_STARTUP,
- "Creating caps for \"%s\" (Command-line \"%s\")\n",
- name, (char*)mmstrings);
-
- // Copy file from archive into RAM.
- // TODO: Give up archive space.
- size_t pa_bytes = round_up(bytes, BASE_PAGE_SIZE);
- lpaddr_t pa = alloc_phys(pa_bytes);
- memcpy((void*)local_phys_to_mem(pa), data, bytes);
-
- struct mem_region* region = &bi->regions[bi->regions_length++];
- region->mr_type = RegionType_Module;
- region->mrmod_slot = spawn_state.modulecn_slot;
- region->mrmod_size = pa_bytes;
- region->mrmod_data = mmstrings - mmstrings_base;
-
- assert((pa & BASE_PAGE_MASK) == 0);
- assert((pa_bytes & BASE_PAGE_MASK) == 0);
-
- while (pa_bytes != 0)
- {
- assert(spawn_state.modulecn_slot
- < (1UL << spawn_state.modulecn->cap.u.cnode.bits));
- // create as DevFrame cap to avoid zeroing memory contents
- err = caps_create_new(
- ObjType_DevFrame, pa, BASE_PAGE_BITS,
- BASE_PAGE_BITS,
- my_core_id,
- caps_locate_slot(
- CNODE(spawn_state.modulecn),
- spawn_state.modulecn_slot++)
- );
- assert(err_is_ok(err));
- pa += BASE_PAGE_SIZE;
- pa_bytes -= BASE_PAGE_SIZE;
- }
- }
- }
- else
- {
- panic("No command-line file.\n");
- }
-}
-
-/// Create physical address range or RAM caps to unused physical memory
-static void
-create_phys_caps(struct capability *physaddrcn_cap, struct bootinfo* bi)
-{
- STARTUP_PROGRESS();
- int i;
- for (i = 0; i < g_phys_mmap->region_count; i++)
- {
- // TODO: Add RegionType_PhyAddr entries for memory mapped I/O
- // regions.
- const phys_region_t* r = &g_phys_mmap->regions[i];
- if (r->limit - r->start >= BASE_PAGE_SIZE) {
- create_caps_to_cnode(r->start, r->limit - r->start,
- RegionType_Empty, &spawn_state, bi);
- }
- }
- g_phys_mmap->region_count = 0;
- STARTUP_PROGRESS();
-}
-
-static void __attribute__ ((noreturn))
-spawn_init(const char* name,
- int32_t kernel_id,
- const uint8_t* initrd_base,
- size_t initrd_bytes)
-{
- assert(0 == kernel_id);
-
- // Create page table for init
-
- init_l1 = (uintptr_t*)alloc_mem_aligned(INIT_L1_BYTES, ARM_L1_ALIGN);
- memset(init_l1, 0, INIT_L1_BYTES);
-
- init_l2 = (uintptr_t*)alloc_mem_aligned(INIT_L2_BYTES, ARM_L2_ALIGN);
- memset(init_l2, 0, INIT_L2_BYTES);
-
- STARTUP_PROGRESS();
-
- /* Allocate bootinfo */
- lpaddr_t bootinfo_phys = alloc_phys(BOOTINFO_SIZE);
- memset((void *)local_phys_to_mem(bootinfo_phys), 0, BOOTINFO_SIZE);
-
- STARTUP_PROGRESS();
-
- /* Construct cmdline args */
- char bootinfochar[16];
- snprintf(bootinfochar, sizeof(bootinfochar), "%u", INIT_BOOTINFO_VBASE);
- const char *argv[] = { "init", bootinfochar };
-
- lvaddr_t paramaddr;
- struct dcb *init_dcb = spawn_module(&spawn_state, name,
- ARRAY_LENGTH(argv), argv,
- bootinfo_phys, INIT_ARGS_VBASE,
- alloc_phys, ¶maddr);
-
- STARTUP_PROGRESS();
-
- /*
- * Create a capability that allows user-level applications to
- * access device memory. This capability will be passed to Kaluga,
- * split up into smaller pieces and distributed to among device
- * drivers.
- *
- * For armv5, this is currently a dummy capability. We do not
- * have support for user-level device drivers in gem5 yet, so we
- * do not allocate any memory as device memory. Some cap_copy
- * operations in the bootup code fail if this capability is not
- * present.
- */
- struct cte *iocap = caps_locate_slot(CNODE(spawn_state.taskcn), TASKCN_SLOT_IO);
- errval_t err = caps_create_new(ObjType_IO, 0, 0, 0, my_core_id, iocap);
- assert(err_is_ok(err));
-
- struct dispatcher_shared_generic *disp
- = get_dispatcher_shared_generic(init_dcb->disp);
- struct dispatcher_shared_arm *disp_arm
- = get_dispatcher_shared_arm(init_dcb->disp);
- assert(NULL != disp);
-
- STARTUP_PROGRESS();
-
- /* Initialize dispatcher */
- disp->udisp = INIT_DISPATCHER_VBASE;
-
- STARTUP_PROGRESS();
- init_dcb->vspace = mem_to_local_phys((lvaddr_t)init_l1);
-
- STARTUP_PROGRESS();
-
- /* Page table setup */
-
- /* Map pagetables into page CN */
- int pagecn_pagemap = 0;
-
- /*
- * ARM has:
- *
- * L1 has 4096 entries (16KB).
- * L2 Coarse has 256 entries (256 * 4B = 1KB).
- *
- * CPU driver currently fakes having 1024 entries in L1 and
- * L2 with 1024 entries by treating a page as 4 consecutive
- * L2 tables and mapping this as a unit in L1.
- */
- caps_create_new(
- ObjType_VNode_ARM_l1,
- mem_to_local_phys((lvaddr_t)init_l1),
- vnode_objbits(ObjType_VNode_ARM_l1), 0,
- my_core_id,
- caps_locate_slot(CNODE(spawn_state.pagecn), pagecn_pagemap++)
- );
-
- STARTUP_PROGRESS();
-
- // Map L2 into successive slots in pagecn
- size_t i;
- for (i = 0; i < INIT_L2_BYTES / BASE_PAGE_SIZE; i++) {
- size_t objbits_vnode = vnode_objbits(ObjType_VNode_ARM_l2);
- assert(objbits_vnode == BASE_PAGE_BITS);
- caps_create_new(
- ObjType_VNode_ARM_l2,
- mem_to_local_phys((lvaddr_t)init_l2) + (i << objbits_vnode),
- objbits_vnode, 0,
- my_core_id,
- caps_locate_slot(CNODE(spawn_state.pagecn), pagecn_pagemap++)
- );
- }
-
- /*
- * Initialize init page tables - this just wires the L1
- * entries through to the corresponding L2 entries.
- */
- STATIC_ASSERT(0 == (INIT_VBASE % ARM_L1_SECTION_BYTES), "");
- for (lvaddr_t vaddr = INIT_VBASE; vaddr < INIT_SPACE_LIMIT; vaddr += ARM_L1_SECTION_BYTES)
- {
- uintptr_t section = (vaddr - INIT_VBASE) / ARM_L1_SECTION_BYTES;
- uintptr_t l2_off = section * ARM_L2_TABLE_BYTES;
- lpaddr_t paddr = mem_to_local_phys((lvaddr_t)init_l2) + l2_off;
- paging_map_user_pages_l1((lvaddr_t)init_l1, vaddr, paddr);
- }
-
- paging_make_good((lvaddr_t)init_l1, INIT_L1_BYTES);
-
- STARTUP_PROGRESS();
-
- printf("XXX: Debug print to make Bram's code work\n");
-
- paging_context_switch(mem_to_local_phys((lvaddr_t)init_l1));
-
- STARTUP_PROGRESS();
-
- // Map cmdline arguments in VSpace at ARGS_BASE
- STATIC_ASSERT(0 == (ARGS_SIZE % BASE_PAGE_SIZE), "");
-
- STARTUP_PROGRESS();
-
- spawn_init_map(init_l2, INIT_VBASE, INIT_ARGS_VBASE,
- spawn_state.args_page, ARGS_SIZE, INIT_PERM_RW);
-
- STARTUP_PROGRESS();
-
- // Map bootinfo
- spawn_init_map(init_l2, INIT_VBASE, INIT_BOOTINFO_VBASE,
- bootinfo_phys, BOOTINFO_SIZE, INIT_PERM_RW);
-
- struct startup_l2_info l2_info = { init_l2, INIT_VBASE };
-
- genvaddr_t init_ep, got_base;
- load_init_image(&l2_info, initrd_base, initrd_bytes, &init_ep, &got_base);
-
- // Set startup arguments (argc, argv)
- disp_arm->enabled_save_area.named.r0 = paramaddr;
- disp_arm->enabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK;
- disp_arm->enabled_save_area.named.rtls = INIT_DISPATCHER_VBASE;
- disp_arm->enabled_save_area.named.r10 = got_base;
-
- disp_arm->got_base = got_base;
-
- struct bootinfo* bootinfo = (struct bootinfo*)INIT_BOOTINFO_VBASE;
- bootinfo->regions_length = 0;
-
- STARTUP_PROGRESS();
-
- create_modules_from_initrd(bootinfo, initrd_base, initrd_bytes);
- debug(SUBSYS_STARTUP, "used %"PRIuCSLOT" slots in modulecn\n", spawn_state.modulecn_slot);
-
- STARTUP_PROGRESS();
- create_phys_caps(&spawn_state.physaddrcn->cap, bootinfo);
-
- STARTUP_PROGRESS();
-
- bootinfo->mem_spawn_core = ~0; // Size of kernel if bringing up others
-
- // Map dispatcher
- spawn_init_map(init_l2, INIT_VBASE, INIT_DISPATCHER_VBASE,
- mem_to_local_phys(init_dcb->disp), DISPATCHER_SIZE,
- INIT_PERM_RW);
-
- STARTUP_PROGRESS();
-
- // NB libbarrelfish initialization sets up the stack.
- disp_arm->disabled_save_area.named.pc = init_ep;
- disp_arm->disabled_save_area.named.cpsr = ARM_MODE_USR | CPSR_F_MASK;
- disp_arm->disabled_save_area.named.rtls = INIT_DISPATCHER_VBASE;
- disp_arm->disabled_save_area.named.r10 = got_base;
-
-#ifdef __XSCALE__
- cp15_disable_cache();
-#endif
-
- printf("Kernel ready.\n");
-
- pit_start();
-
- // On to userland...
- STARTUP_PROGRESS();
- dispatch(init_dcb);
-
- panic("Not reached.");
-}
-
-void arm_kernel_startup(phys_mmap_t* mmap,
- lpaddr_t initrd_base,
- size_t initrd_bytes)
-{
- g_phys_mmap = mmap;
-
- STARTUP_PROGRESS();
-
-#ifdef __XSCALE__
- //Hardcoded because bootloader alter image if we pass the correct location
- //Size of image is obtained by header file which is generated during compilation
- initrd_base = 0x20000000;
- initrd_bytes = romfs_cpio_archive_size;
-#endif
-
- const uint8_t* initrd_cpio_base = (uint8_t*)local_phys_to_mem(initrd_base);
-
- if (!cpio_archive_valid(initrd_cpio_base, initrd_bytes))
- {
- panic("Invalid initrd filesystem\n");
- }
-
- /* allocate initial KCB */
- kcb_current = (struct kcb *) local_phys_to_mem(alloc_phys(sizeof(*kcb_current)));
- memset(kcb_current, 0, sizeof(*kcb_current));
- assert(kcb_current);
-
- spawn_init(BSP_INIT_MODULE_NAME, 0, initrd_cpio_base, initrd_bytes);
-}
+++ /dev/null
-/**
- * \file
- * \brief Bootstrap the kernel for ARMv7-M processors, specifically the
- * cortex-m3 on the OMAP44XX This code is
- * entered from the bootloader (typically arm_molly, RedBoot,
- * etc.).
- */
-/*
- * Copyright (c) 2009 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#ifndef __ASSEMBLER__
-#define __ASSEMBLER__ 1
-#endif
-
-#include <barrelfish_kpi/flags_arch.h> // ARM_MODE_MASK
-#include <offsets.h> // BOOT_STACK_PHYS
-
- .text
-// .arm
-
- .globl start, halt, got_base
- .extern kernel_stack, glbl_core_data
-
- // Used to track phys memory allocator limit globally.
- alloc_top .req r11
-
-start:
-/*
- //idea is that the cortex-A9 has already started the MMU, and included all pagemappings
- //that we need to setup the rest
-
- // On entry:
- //
- // MMU already enabled, TLB filled with necessary mappings to bootstrap
- // Cache disabled
- // CPU is in priviledged thread mode.
- //
-
-*/
- //init stack
- ldr r6, =kernel_stack
- mov sp, r6//can not directly ldr to sp, so use r6 inbetween
- movw r6, #KERNEL_STACK_SIZE//can not directly add big immediates, so move it into register first
- add sp, r6 //sp = &kernel_stack+KERNEL_STACK_SIZE
-
-
- ldr r0, =got_base
- mov PIC_REGISTER, r0
- // equivalent to: ldr PIC_REGISTER, =got_base
-
- //prepare argument
- mov r0, r2
- //do a long call to compensate for shorter range
- ldr r6, =arch_init//shorthand, loads the value from memory
- bx r6
- //equivalent to: b arch_init
- b halt
-
-
-/**
- * extern "C" void halt(void) __attribute__((noreturn))
- */
-halt:
- b .
-
-/**********************************************************************/
-.ltorg
-
-got_base:
- .word // Initialized by linker
-
- .end
+++ /dev/null
-/*
- * Copyright (c) 2007, 2008, 2009, ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#ifndef __ASSEMBLER__
-#define __ASSEMBLER__
-#endif // __ASSEMBLER__
-
-#include <asmoffsets.h> // OFFSETOF etc.
-#include <barrelfish_kpi/registers_arch.h> // CPSR_REG etc.
-#include <barrelfish_kpi/registers_pushed_arm_v7m.h> // PC_REG_PUSHED etc.
-#include <barrelfish_kpi/flags_arch.h> // CPSR_IF_MASK etc.
-#include <exceptions.h>
-
-//#define EXCEPTION_MODE_STACK_BYTES 256
-#define HANDLER_MODE_STACK_BYTES 8192
-
-#define VECTORTABLE_BYTES 320 //16 system interrupts + 64 external interrupts, 4 bytes each
-
-
- .syntax unified
- .text
-
- .globl exceptions_init
- .globl exceptions_early_init
- .globl vectortable
- .globl irq_save_pushed_area_top
- //
- .balign 4096 //so we can treat this as just a page when setting up the MMU
- //XXX: "balign" seems to be GNU-specific.
- //other arm assemblers use the corresponding power of two as their argument instead
-
-
-vectortable: //where the interrupt handlers will be looked up
- .space VECTORTABLE_BYTES, 0
- //XXX: maybe we rather want the table in .data instead of .text, but then
- //we will have to make sure both the page with the table AND the page with the
- //handlers will be accessible (mapped in cache MMU)
-
- //
- // Handler mode stack
- //
- // used whenever we transfer to handler mode (priviledged) from an unpriviledged mode,
- // in which case we can assume that it is safe to overwrite all of it
- // DO NOT USE THIS WHEN CAME FROM HANDLER MODE IN THE FIRST PLACE
- // all exception handlers that are allowed to interrupt others need to check first
- // if they interrupted another handler, in which case they are not allowed to set their
- // own stack!
-handler_stack:
- .space HANDLER_MODE_STACK_BYTES, 0
-handler_stack_top:
-
-irq_save_area:
- .space (NUM_REGS * 4), 0
-
-irq_save_pushed_area: //used when we switch to a process with uninitialized stack
- .space (NUM_REGS_PUSHED * 4), 0
-irq_save_pushed_area_top:
-
-got_for_handler_mode:
- .word 0
-
-
-
-
- // void exceptions_early_init(void)
- //
- // Assumes running in priviledged thread Mode.
- // sets up the special handler used to cleanly transition into handler mode
- // DOES NOT RETURN, instead triggers the special handler
- //
-exceptions_early_init:
- //use SVcall, because this is always enabled and can be triggered by a single instruction
- //XXX: using the fact that whatever vector table we are currently using,
- //it will be mapped to address 0
- mov r2, #0 // base of vectortable, where the handler will be stored
- mov r0, # ARM_7M_EVECTOR_SVCALL
- adr r1, initialization_handler
- add r2, r2, r0 , LSL #2 // vectortable + 4*vector_index
- orr r1, #1 //lsb of handler must be 1 to indicate thumb mode
- str r1, [r2] //write handler address into table
- //change thread mode stack pointer (the only banked register)
- mrs r1, MSP
- msr PSP, r1 //copy main stack pointer to thread stack pointer
- mov r1, #2
- msr control, r1 //set threadmode stackpointer to PSP
- //trigger the special exception -> will never return
- svc #0
-
-
- //special handler that may only be triggered once -> used so we are in handler mode
- //gives control over to initialization code in armv7-m/init.c
-initialization_handler:
- mov r1, #1
- msr control, r1 //set threadmode unpriviledged
- ldr r4, =text_init_continued
- bx r4
-
-
- //
- // void exceptions_init(void)
- //
- // Assumes running in handler Mode.
- //
-exceptions_init:
- push {lr}
- push {r0-r4}
- ldr r0, null_handler
- ldr r1, =vectortable
-$exceptions_install_handlers:
- mov r0, # ARM_7M_EVECTOR_MEM
- ldr r1, =pagefault_handler
- bl exceptions_install_handler
- mov r0, # ARM_7M_EVECTOR_BUS
- ldr r1, =pagefault_handler
- bl exceptions_install_handler
- mov r0, # ARM_7M_EVECTOR_SYSTICK
- ldr r1, =generic_irq_handler
- bl exceptions_install_handler
- mov r0, # ARM_7M_EVECTOR_USAGE
- ldr r1, =usagefault_handler
- bl exceptions_install_handler
- mov r0, # ARM_7M_EVECTOR_SVCALL
- ldr r1, =swi_handler
- bl exceptions_install_handler
- mov r0, # ARM_7M_EVECTOR_HARDFAULT
- ldr r1, =generic_irq_handler
- bl exceptions_install_handler
- mov r0, # ARM_7M_EVECTOR_NMI
- ldr r1, =generic_irq_handler
- bl exceptions_install_handler
-$exceptions_save_got:
- ldr r0, = got_for_handler_mode
- mov r1, PIC_REGISTER
- str r1, [r0]
-$exceptions_init_done:
- //ldmfd sp!, {pc}
- pop {r0-r4}
- pop {pc}
-
-
- //
- //void exceptions_install_handler(int vector_index, void (*handler)(void)
- // writes entry into vectortable (and nothing else)
- //
-exceptions_install_handler:
- ldr r2, =vectortable // base of vectortable, where the handler will be stored
- add r2, r2, r0 , LSL #2 // vectortable + 4*vector_index
- orr r1, #1 //lsb of handler must be 1 to indicate thumb mode
- str r1, [r2] //write handler address into table
- bx lr
- //
- // void null_handler(void)
- //
-null_handler:
- b .
-
-
- // Macro definition to get pointer to arch specific dispatcher
- //
- // Logical equivalent of C function with same name
- //
-.macro get_dispatcher_shared_arm out
- ldr \out, = dcb_current // out = address of pointer to dcb_current
- ldr \out, [\out] // out = dcb_current
- ldr \out, [\out, #OFFSETOF_DCB_DISP] //now ptr to dispatcher_shared_arm
-.endm
-
- //
- // Macro to determine if dispatcher is disabled.
- //
- // pc and disp arguments are unmodified.
- // out contains result
- //
-.macro disp_is_disabled disp, pc, out
- // disp->disabled || (disp->crit_pc_lo <= pc && pc < disp->crit_pc_hi)
- ldrb \out, [\disp, #OFFSETOF_DISP_DISABLED]
- cmp \out, #1
- IT hs
- bhs 0f // disp->disabled >= 0 | disabled
- // disp->disabled = false
- ldr \out, [\disp, #OFFSETOF_DISP_CRIT_PC_LOW]
- cmp \out, \pc
- ITt hi
- movhi \out, #0
- bhi 0f // disp->crit_pc_low > pc | enabled
- ldr \out, [\disp, #OFFSETOF_DISP_CRIT_PC_HIGH]
-
- cmp \pc, \out
- ITe hs
- movhs \out, #0 // pc >= disp->crit_pc_high | enabled
- movlo \out, #1 // pc < disp->crit_pc_high | disable
-0:
-.endm
-
-
- //
- // Macro to initialize handler mode stack
- //
-.macro init_handler_stack
- ldr sp, =handler_stack_top
-.endm
-
- //
- // Macro to initialize handler pic register
- //
-.macro init_handler_pic_register
- ldr PIC_REGISTER, = got_for_handler_mode
- ldr PIC_REGISTER, [PIC_REGISTER]
-.endm
-
-
- //
- // Macro to save all registers (as they were at the moment of interrupt)
- // into context
- // pops from threadmode stack (PSP -> PSP - 8*4)
- // only temp_regs will be clobbered
- //
-.macro save_context context, temp_reg1, temp_reg2
- .if CPSR_REG <> 0
- .err "Invariant failure: CPSR offset != 0"
- .endif
- .if PC_REG <> 16
- .err "Invariant failure: PC offset != 16"
- .endif
- mrs \temp_reg1, PSP //thread mode stack
- ldr \temp_reg2, [\temp_reg1, #(R0_REG_PUSHED *4)] //read pushed r0
- str \temp_reg2, [\context, #(R0_REG*4)] //copy to context.r0
- ldr \temp_reg2, [\temp_reg1, #(R1_REG_PUSHED *4)] //read pushed r1
- str \temp_reg2, [\context, #(R1_REG *4)] //copy to context.r1
- ldr \temp_reg2, [\temp_reg1, #(R2_REG_PUSHED *4)] //read pushed r2
- str \temp_reg2, [\context, #(R2_REG *4)] //copy to context.r2
- ldr \temp_reg2, [\temp_reg1, #(R3_REG_PUSHED *4)] //read pushed r3
- str \temp_reg2, [\context, #(R3_REG *4)] //copy to context.r3
- ldr \temp_reg2, [\temp_reg1, #(R12_REG_PUSHED *4)] //read pushed r12
- str \temp_reg2, [\context, #(R12_REG * 4)] //copy to context.r12
- ldr \temp_reg2, [\temp_reg1, #(LR_REG_PUSHED *4)] //read pushed lr
- str \temp_reg2, [\context, #(LR_REG * 4)] //copy to context.lr
- ldr \temp_reg2, [\temp_reg1, #(PC_REG_PUSHED *4)] //read pushed pc
- str \temp_reg2, [\context, #(PC_REG * 4)] //copy to context.pc
- ldr \temp_reg2, [\temp_reg1, #(XPSR_REG_PUSHED *4)] //read pushed xpsr
- str \temp_reg2, [\context, #(CPSR_REG * 4)] //copy to context.xpsr
- add \temp_reg1, #(NUM_REGS_PUSHED*4) //we read the pushed registers -> restore stack
- str \temp_reg1, [\context, #(SP_REG * 4)] //copy to context.sp
- //store rest of registers in context
- add \temp_reg1, \context, #(R4_REG * 4) //point to first unpushed register
- stmia \temp_reg1, {r4-r11} //store rest
-.endm
-
-
-
-/*
- * void generic_irq_handler(void)
- *
- * handler for pretty much any IRQ we get, except system calls (as those take arguments),
- * and traps (or rather, what the dispatcher would see as traps -- pagefaults, usage faults)
- * checks if we interrupted userspace or kernelspace,
- * reads out IRQ number,
- * calls a handler that does the case distinction in C
- */
-generic_irq_handler:
- and r1, lr, #8 // r1 is now 0 if we come from handler mode
- cbnz r1, generic_irq_handler_user //compares without changing condition flags
-
-generic_irq_handler_kernel: //no "$" because that bloated the layout, reducing the branch range
- mov r2, sp //place where pushed registers start
- ldr r1, [sp, #(PC_REG_PUSHED * 4)] //this should be where the pushed pc ends up
- ldr r3, =fatal_kernel_fault
- bx r3
-generic_irq_handler_user:
- init_handler_stack
- get_dispatcher_shared_arm r2
- mrs r0, PSP
- ldr r0, [r0, #(PC_REG_PUSHED*4)] // r0 = faulting pc
- disp_is_disabled r2, r0, r1 // r1 = 1 if disabled, else 0
- cmp r1, #0
- ITe eq
- addeq r1, r2, #OFFSETOF_DISP_ENABLED_AREA
- addne r1, r2, #OFFSETOF_DISP_DISABLED_AREA
- save_context r1, r3, r2 // r1 = save area
- init_handler_pic_register //only set after saving context
- mrs r0, IPSR //what IRQ are we currently handling
- ldr r3, =handle_irq
- bx r3
-
-/*
- * void pagefault_handler(void)
- *
- * handler just for pagefaults (which in this case are bus faults or mem faults)
- */
-pagefault_handler:
- and r1, lr, #8 // r1 is now 0 if we come from handler mode
- cbnz r1, pagefault_handler_user //compares without changing condition flags
-
-pagefault_handler_kernel:
- mov r2, sp //place where pushed registers start
- ldr r1, [sp, #(PC_REG_PUSHED * 4)] //this should be where the pushed pc ends up
- ldr r3, =fatal_kernel_fault
- bx r3
-pagefault_handler_user:
- init_handler_stack
- get_dispatcher_shared_arm r2
- mrs r0, PSP
- ldr r0, [r0, #(PC_REG_PUSHED*4)] // r0 = faulting pc
- disp_is_disabled r2, r0, r1 // r1 = 1 if disabled, else 0
- cmp r1, #0
- ITe eq
- addeq r1, r2, #OFFSETOF_DISP_ENABLED_AREA
- addne r1, r2, #OFFSETOF_DISP_TRAP_AREA
- save_context r1, r3, r2 // r1 = save area
- mov r0, r1 //save area must be first argument
- init_handler_pic_register //only set after saving context
- ldr r3, =handle_user_page_fault
- bx r3
-
-/*
- * void usagefault_handler(void)
- *
- * handler just for usagefaults, which can be:
- * undefined instruction
- * unaligned access
- * division by 0
- */
-usagefault_handler:
- and r1, lr, #8 // r1 is now 0 if we come from handler mode
- cbnz r1, usagefault_handler_user //compares without changing condition flags
-
-usagefault_handler_kernel:
- mov r2, sp //place where pushed registers start
- ldr r1, [sp, #(PC_REG_PUSHED * 4)] //this should be where the pushed pc ends up
- ldr r3, =fatal_kernel_fault
- bx r3
-usagefault_handler_user:
- init_handler_stack
- get_dispatcher_shared_arm r2
- mrs r0, PSP
- ldr r0, [r0, #(PC_REG_PUSHED*4)] // r0 = faulting pc
- disp_is_disabled r2, r0, r1 // r1 = 1 if disabled, else 0
- cmp r1, #0
- ITe eq
- addeq r1, r2, #OFFSETOF_DISP_ENABLED_AREA
- addne r1, r2, #OFFSETOF_DISP_TRAP_AREA
- save_context r1, r3, r2 // r1 = save area
- mov r0, r1 //save area must be first argument
- init_handler_pic_register //only set after saving context
- ldr r3, =handle_user_undef
- bx r3
-
- //
- // void swi_handler(void)
- //
- // handles all software interrupts (SVCALL)
- //
- // r0 = encoded syscall ordinal
- // r1 = syscall arg0
- // r2 = syscall arg1
- // ...
- // r7 = syscall arg6
- //
- // For now the system saves the caller's context here, because
- // some fraction of system calls do not return directly.
- //
-swi_handler:
- .if SYSCALL_REG <> 0
- .error "Syscall entry broken. Expected ordinal reg to be r0."
- .endif
-
-//registers r0-r3,r12 are available for scratch use, since they are already on PSP stack
- and r1, lr, #8 // r1 is now 0 if we come from handler mode
- cbnz r1, swi_user //compares without changing condition flags
-swi_kernel:
- ldr r3, =sys_syscall_kernel
- bx r3
-swi_user: //much like generic_irq_handler, but the save area is in r0
- init_handler_stack
- get_dispatcher_shared_arm r2
- mrs r0, PSP
- ldr r0, [r0, #(PC_REG_PUSHED*4)] // r0 = faulting pc
- disp_is_disabled r2, r0, r1 // r1 = 1 if disabled, else 0
- cmp r1, #0
- ITe eq
- addeq r1, r2, #OFFSETOF_DISP_ENABLED_AREA
- addne r1, r2, #OFFSETOF_DISP_DISABLED_AREA
- save_context r1, r3, r2 // r1 = save area
- mov r0, r1 //sys_syscall expects the context to be in r0
- init_handler_pic_register //only set this after saving context!
- ldr r3, =sys_syscall
- bx r3
-
+++ /dev/null
-/**
- * \file
- * \brief ARMv7-M upcalls
- */
-
-/*
- * Copyright (c) 2007, 2008, 2009, ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <dispatch.h>
-#include <init.h>
-#include <arm.h>
-#include <arm_hal.h>
-#include <exec.h>
-#include <exceptions.h>
-#include <misc.h>
-#include <barrelfish_kpi/registers_pushed_arm_v7m.h>//for autopushed register access
-
-static arch_registers_state_t upcall_state;//XXX: is this even used??
-
-extern uint32_t ctr;
-
-/*
- * On armv7-m, the registers r0-r3,r12,lr,pc,xpsr are popped from the stack
- * whenever an exception returns -> we copy those values onto the thread mode stack after
- * restoring the others
- */
-static inline __attribute__((noreturn))
-void do_resume(uint32_t *regs)
-{
- STATIC_ASSERT(CPSR_REG == 0, "wrong register layout");
- STATIC_ASSERT(R0_REG == 1, "wrong register layout");
- STATIC_ASSERT(PC_REG == 16, "wrong register layout");
- STATIC_ASSERT(XPSR_REG_PUSHED == 7, "wrong register layout");
- STATIC_ASSERT(R0_REG_PUSHED == 0, "wrong register layout");
- STATIC_ASSERT(PC_REG_PUSHED == 6, "wrong register layout");
-
-
-
- if (((arch_registers_state_t*) regs)->named.stack == 0){
- printf("uninitialized stack pointer -> point to irq_save_pushed_area_top\n");
- ((arch_registers_state_t*) regs)->named.stack = (uint32_t) irq_save_pushed_area_top;
- printf("new stack pointer: 0x%x\n", ((arch_registers_state_t*) regs)->named.stack);
- }
-
- //this is probably the ONLY time we do not have to adjust a future pc - we have to
- //adjust the XPSR instead...
- //the EPSR part of the XPSR is normally ignored (mrs reads it as 0, msr is ignored),
- //but when restoring the XPSR on modeswitch, it is actually read.
- //This means we have to always ensure the Thumb-bit is set
- if ((((arch_registers_state_t*) regs)->named.cpsr & 0x01000000) == 0){
- printf("EPSR thumb bit not set -> fixed\n");
- ((arch_registers_state_t*) regs)->named.cpsr |= 0x01000000;
- printf("new XPSR register: 0x%x\n", ((arch_registers_state_t*) regs)->named.cpsr);
- //should only actually happen when we first execute a new process
- }
-
-
- __asm volatile(
- "mov r0, %[regs] \n\t" //address where the regs are
- "ldr r1, [r0, #56] \n\t" //stored stack pointer
- "sub r1, #32 \n\t" //allocate stack space for 8 registers
- //copy the 8 expected registers
- //XXX: could probably be shortened by using ldm, but only for the first 4 registers
- "ldr r2, [r0,#(" XTR(R0_REG) "*4)] \n\t" //copy r0 entry, using r2 as temp
- "str r2, [r1,#(" XTR(R0_REG_PUSHED) "*4)]\n\t"
- "ldr r2, [r0,#(" XTR(R1_REG) "*4)] \n\t" //copy r1 entry, using r2 as temp
- "str r2, [r1,#(" XTR(R1_REG_PUSHED) "*4)]\n\t"
- "ldr r2, [r0,#(" XTR(R2_REG) "*4)] \n\t" //copy r2 entry, using r2 as temp
- "str r2, [r1,#(" XTR(R2_REG_PUSHED) "*4)]\n\t"
- "ldr r2, [r0,#(" XTR(R3_REG) "*4)] \n\t" //copy r3 entry, using r2 as temp
- "str r2, [r1,#(" XTR(R3_REG_PUSHED) "*4)]\n\t"
- "ldr r2, [r0,#(" XTR(R12_REG) "*4)] \n\t" //copy r12 entry, using r2 as temp
- "str r2, [r1,#(" XTR(R12_REG_PUSHED)"*4)]\n\t"
- "ldr r2, [r0,#(" XTR(LR_REG) "*4)] \n\t" //copy lr entry, using r2 as temp
- "str r2, [r1,#(" XTR(LR_REG_PUSHED) "*4)]\n\t"
- "ldr r2, [r0,#(" XTR(PC_REG) "*4)] \n\t" //copy pc entry, using r2 as temp
- "str r2, [r1,#(" XTR(PC_REG_PUSHED) "*4)]\n\t"
- "ldr r2, [r0] \n\t" //copy xpsr entry, using r2 as temp
- "str r2, [r1,#28] \n\t"
- //set thread stack pointer
- "msr PSP, r1 \n\t" //set thread stack pointer to saved context
- //restore unpushed registers: r4-r11
- "add r0, #(" XTR(R4_REG) "*4) \n\t" //point to r4 entry
- "ldmia r0, {r4-r11} \n\t" //restore r4 - r11
- "ldr lr, =#0xFFFFFFFD \n\t" //special return address to change modes
- "bx lr \n\t" //actual context switch
- :: [regs] "r" (regs) : "lr");
-
- panic("do_resume returned.");
-}
-
-/// Ensure context is for user-mode with interrupts enabled.
-static inline void
-ensure_user_mode_policy(arch_registers_state_t *state)
-{
- //this should be a no-op on armv7-m:
- //user mode is ensured by the return address used in do_resume
- //exeptions can be tail-chained instead of preemting each other, meaning we never
- //have to completely disable them
-}
-
-/**
- * \brief Go to user-space at entry point 'entry'.
- *
- * This function goes to user-space and starts executing the program at
- * its entry point at virtual address 'entry'.
- *
- * \param entry Entry point address of program to execute.
- */
-void __attribute__ ((noreturn))
-execute(lvaddr_t entry)
-{
- dispatcher_handle_t handle = dcb_current->disp;
- struct dispatcher_shared_arm *disp_arm = get_dispatcher_shared_arm(handle);
-
- arch_registers_state_t *state = &upcall_state;
- assert(0 != disp_arm->got_base);
-
- state->named.r10 = disp_arm->got_base;
-
- struct dispatcher_shared_generic *disp_gen
- = get_dispatcher_shared_generic(handle);
-
- state->named.rtls = disp_gen->udisp;
-
- state->named.pc = entry;
- ensure_user_mode_policy(state);
- do_resume(state->regs);
-}
-
-/**
- * \brief Resume the given user-space snapshot.
- *
- * This function resumes user-space execution by restoring the CPU
- * registers with the ones given in the array, pointed to by 'state'.
- */
-uint32_t ctr=0;
-void __attribute__ ((noreturn)) resume(arch_registers_state_t *state)
-{
- ctr++;
-
- state->named.rtls = arch_get_thread_register();
-
- ensure_user_mode_policy(state);
-
- /*
- This function succeeds the first time executed, i.e.
- when init is started for the first time.
- If we hold the execution here after the first execption, we are still good
- */
- // while(ctr>1);
- do_resume(state->regs);
-}
-
-void wait_for_interrupt(void)
-{
-/*XXX: WARNING: the way this is currently implemented, we will probably never wake up
- * we are already in handler mode, and the interrupt we are waiting for does not have
- * a higher priority, so it will only be taken when we exit -- which is never (I think)
- * (was not able to test it with IPIs, but we do stop servicing timer interrupts)
- *
- * Solution: in this function, first increase the priority of IPIs to the maximum
- * write a separate handler for IPIs, that first checks where it came from.
- * if it came from handler mode, it must have interrupted this wait
- * -> set priority back down again and then handle the interrupt normally
- * (no context save necessary)
- * if it came from thread mode, treat it as any other interrupt (context save etc.)
- *
- * always setting the the priority back down will ensure we never interrupt the kernel
- * while it is doing actual work
- */
- __asm volatile(
- "0: \n\t"
- "wfi \n\t"
- "b 0b \n\t" :::);
-
- panic("wfi returned");
-}
+++ /dev/null
-/*
- * Copyright (c) 2009-2013 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <kernel.h>
-#include <dispatch.h>
-#include <arm.h>
-#include <arm_hal.h> //needed for nvic device
-#include <exceptions.h>
-#include <exec.h>
-#include <misc.h>
-#include <stdio.h>
-#include <wakeup.h>
-#include <paging_kernel_arch.h> //for mmu device
-#include <dev/omap/omap44xx_cortex_m3_nvic_dev.h>
-
-
-
-//TODO: heteropanda: actually handle the interrupts, instead of aborting
-
-/*
- * Try to find out what address generated page fault, and then tell the dispatcher what
- * happened. Some faults will not be recoverable (e.g. stack faults), because the
- * context has already been lost
- */
-void handle_user_page_fault(arch_registers_state_t* save_area)
-{
- lvaddr_t fault_address;//not passed as argument, because there is not just one place to look
- /*
- //print out registers for debugging
- printf("page fault. registers:\n");
- for(uint32_t i = 0; i<NUM_REGS; i++){
- printf("0x%x\n", save_area->regs[i]);
- }
- uint32_t regval;
- __asm volatile ("mrs %[regval], xpsr" : [regval] "=r"(regval));
- printf("current XPSR register: 0x%x\n", regval);
-
- printf("M3 MMU address: 0x%x\n", *((uint32_t*) &mmu));
- printf("M3 MMU_FAULT_AD register: 0x%x\n", omap44xx_mmu_fault_ad_rd(&mmu));
- printf("M3 MMU_FAULT_STATUS register: 0x%x\n", omap44xx_mmu_fault_status_rd(&mmu));
- printf("M3 MMU_FAULT_PC register: 0x%x\n", omap44xx_mmu_fault_pc_rd(&mmu));
- printf("M3 MMU_IRQSTATUS register: 0x%x\n", omap44xx_mmu_irqstatus_rd(&mmu));
-
- printf("ICTR: 0x%x\n", omap44xx_cortex_m3_nvic_ICTR_rd(&nvic));
- printf("CPUID_BASE: 0x%x\n", omap44xx_cortex_m3_nvic_CPUID_BASE_rd(&nvic));
- printf("ICSR: 0x%x\n", omap44xx_cortex_m3_nvic_ICSR_rd(&nvic));
- printf("VTOR: 0x%x\n", omap44xx_cortex_m3_nvic_VTOR_rd(&nvic));
- printf("AIRCR: 0x%x\n", omap44xx_cortex_m3_nvic_AIRCR_rd(&nvic));
- printf("CCR: 0x%x\n", omap44xx_cortex_m3_nvic_CCR_rd(&nvic));
- printf("SHCSR: 0x%x\n", omap44xx_cortex_m3_nvic_SHCSR_rd(&nvic));
- printf("CFSR: 0x%x\n", omap44xx_cortex_m3_nvic_CFSR_rd(&nvic));
- printf("BFAR: 0x%x\n", omap44xx_cortex_m3_nvic_BFAR_rd(&nvic));
- printf("SYSTICK_CTRL: 0x%x\n", omap44xx_cortex_m3_nvic_SYSTICK_CTRL_rd(&nvic));
- printf("SYSTICK_CALV: 0x%x\n", omap44xx_cortex_m3_nvic_SYSTICK_CALV_rd(&nvic));
- */
- if (omap44xx_cortex_m3_nvic_SHCSR_busfaultact_rdf(&nvic)){
- //triggered by bus fault
- if (omap44xx_mmu_irqstatus_rd(&mmu)){
- //L2 MMU triggered fault: either no valid mapping, or two mappings in TLB
- //XXX: cachemarker: once we have chaching enabled, this is the place to
- //look at table entry for special permission bits.
-
- //XXX: MMU_FAULT_ADDR register seems to just contain the last address that was
- //requested. By this time this is probably just a kernelspace address.
- //I am not sure if the M3 can actually find out what the faulting address really was
- fault_address = omap44xx_mmu_fault_ad_rd(&mmu);
- }
- else{
- //"regular" bus fault -> look in NVIC entries
- if (omap44xx_cortex_m3_nvic_CFSR_bfarvalid_rdf(&nvic)){
- //bus fault address register valid
- fault_address = omap44xx_cortex_m3_nvic_BFAR_rd(&nvic);
- }
- else{
- //one of the bus faults that do not write the BFAR -> faulting address
- //literally unknown to system
- printk(LOG_WARN, "user bus fault with unknown faulting address\n");
- fault_address = (lvaddr_t) NULL;
- }
- }
- }
- else{
- //memory management fault (probably access violation)
- if (omap44xx_cortex_m3_nvic_CFSR_mmarvalid_rdf(&nvic)){
- //MMAR contains faulting address
- fault_address = omap44xx_cortex_m3_nvic_MMAR_rd(&nvic);
- }
- else{
- //MMAR not written. probably executing in noexecute region
- assert(omap44xx_cortex_m3_nvic_CFSR_iaccviol_rdf(&nvic));
- //so we can assume the pc caused the fault
- fault_address = save_area->named.pc;
- }
- }
-
- lvaddr_t handler;
- struct dispatcher_shared_arm *disp = get_dispatcher_shared_arm(dcb_current->disp);
- uintptr_t saved_pc = save_area->named.pc;
-
- disp->d.disabled = dispatcher_is_disabled_ip(dcb_current->disp, saved_pc);
- bool disabled = (disp->d.disabled != 0);
-
- assert(dcb_current->disp_cte.cap.type == ObjType_Frame);
-
- printk(LOG_WARN, "user page fault%s in '%.*s': addr %"PRIxLVADDR
- " IP %"PRIxPTR"\n",
- disabled ? " WHILE DISABLED" : "", DISP_NAME_LEN,
- disp->d.name, fault_address, saved_pc);
-
- if (disabled) {
- assert(save_area == &disp->trap_save_area);
- handler = disp->d.dispatcher_pagefault_disabled;
- dcb_current->faults_taken++;
- }
- else {
- assert(save_area == &disp->enabled_save_area);
- handler = disp->d.dispatcher_pagefault;
- }
-
- if (dcb_current->faults_taken > 2) {
- printk(LOG_WARN, "handle_user_page_fault: too many faults, "
- "making domain unrunnable\n");
- dcb_current->faults_taken = 0; // just in case it gets restarted
- scheduler_remove(dcb_current);
- dispatch(schedule());
- }
- else {
- // Upcall to dispatcher
-
-
- struct dispatcher_shared_generic *disp_gen =
- get_dispatcher_shared_generic(dcb_current->disp);
-
- union registers_arm resume_area;
-
- //make sure we do not accidentaly create an IT block when upcalling
- resume_area.named.cpsr = 0;
-
- resume_area.named.pc = handler;
- resume_area.named.r0 = disp_gen->udisp;
- resume_area.named.r1 = fault_address;
- resume_area.named.r2 = 0;
- resume_area.named.r3 = saved_pc;
- resume_area.named.rtls = disp_gen->udisp;
- resume_are