merge with master
This commit is contained in:
commit
911d135e2f
54 changed files with 879 additions and 286 deletions
54
CONTRIBUTORS.md
Normal file
54
CONTRIBUTORS.md
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
Contributors
|
||||
------------
|
||||
|
||||
People who contributed to the seL4 code, design, or documentation in this
|
||||
repository (in alphabetical order).
|
||||
|
||||
* June Andronick, NICTA & UNSW
|
||||
* Ali Akguel, NICTA
|
||||
* Joel Beeren, NICTA
|
||||
* Bernard Blackham, NICTA & UNSW
|
||||
* Timothy Bourke, NICTA
|
||||
* Andrew Boyton, NICTA & UNSW
|
||||
* Matthew Brassil, NICTA
|
||||
* Aleksander Budzynowski, NICTA & UNSW
|
||||
* Manuel Chakravarty, NICTA & UNSW
|
||||
* Xi Ma Chen, NICTA
|
||||
* Nahida Chowdhury, NICTA
|
||||
* Peter Chubb, NICTA
|
||||
* David Cock, NICTA & UNSW
|
||||
* Adrian Danis, NICTA
|
||||
* Matthias Daum, NICTA & UNSW
|
||||
* Philip Derrin, NICTA
|
||||
* Dhammika Elkaduwe, NICTA & UNSW
|
||||
* Kevin Elphinstone, NICTA & UNSW
|
||||
* Matthew Fernandez, NICTA & UNSW
|
||||
* Peter Gammie, NICTA
|
||||
* Xin Gao, NICTA
|
||||
* David Greenaway, NICTA & UNSW
|
||||
* Matthew Grosvenor, NICTA
|
||||
* Lukas Haenel, NICTA
|
||||
* Gernot Heiser, NICTA & UNSW
|
||||
* Benjamin Kalman, NICTA
|
||||
* Justin King-Lacroix, NICTA
|
||||
* Gerwin Klein, NICTA & UNSW
|
||||
* Rafal Kolanski, NICTA & UNSW
|
||||
* Alexander Kroh, NICTA
|
||||
* Etienne Le Sueur, NICTA & UNSW
|
||||
* Corey Lewis, NICTA
|
||||
* Japheth Lim, NICTA
|
||||
* Anna Lyons, NICTA & UNSW
|
||||
* Stephanie McArthur, NICTA
|
||||
* Sam McNally, NICTA
|
||||
* Toby Murray, NICTA & UNSW
|
||||
* Ameya Palande, NICTA
|
||||
* Max R.D. Parmer
|
||||
* Sean Peters, NICTA
|
||||
* Simon Rodgers, NICTA
|
||||
* Sean Seefried, NICTA
|
||||
* Thomas Sewell, NICTA & UNSW
|
||||
* Michael von Tessin, NICTA & UNSW
|
||||
* Adam Walker, NICTA
|
||||
* James Wilmot, NICTA
|
||||
* Simon Winwood, NICTA
|
||||
* Jiawei Xie, NICTA
|
||||
2
Kconfig
2
Kconfig
|
|
@ -202,7 +202,7 @@ menu "seL4 System Parameters"
|
|||
|
||||
config MAX_NUM_BOOTINFO_DEVICE_REGIONS
|
||||
int "Max number of bootinfo device regions"
|
||||
default 200
|
||||
default 199
|
||||
|
||||
config MAX_NUM_BOOTINFO_UNTYPED_CAPS
|
||||
int "Max number of bootinfo untyped caps"
|
||||
|
|
|
|||
12
Makefile
12
Makefile
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
ARCH_LIST:=arm ia32
|
||||
CPU_LIST:=arm1136jf-s ixp420 cortex-a8 cortex-a9 cortex-a15
|
||||
PLAT_LIST:=imx31 pc99 integratorcp ixp420 omap3 am335x exynos4 exynos5 imx6 apq8064
|
||||
PLAT_LIST:=imx31 pc99 ixp420 omap3 am335x exynos4 exynos5 imx6 apq8064
|
||||
ARMV_LIST:=armv6 armv7-a
|
||||
|
||||
ifndef SOURCE_ROOT
|
||||
|
|
@ -343,7 +343,7 @@ endif
|
|||
ifndef NK_CFLAGS
|
||||
ifeq (${ARCH}, arm)
|
||||
CFLAGS += -mtune=${CPU} -marm -march=${ARMV}
|
||||
ASFLAGS += -mcpu=${CPU} -march=${ARMV}
|
||||
ASFLAGS += -Wa,-mcpu=${CPU} -Wa,-march=${ARMV}
|
||||
DEFINES += -D$(shell echo ${ARMV}|tr [:lower:] [:upper:]|tr - _)
|
||||
ifeq (${CPU},cortex-a8)
|
||||
DEFINES += -DARM_CORTEX_A8
|
||||
|
|
@ -356,7 +356,7 @@ endif
|
|||
|
||||
ifeq (${ARCH}, ia32)
|
||||
CFLAGS += -m32 -mno-mmx -mno-sse
|
||||
ASFLAGS += --32
|
||||
ASFLAGS += -Wa,--32
|
||||
endif
|
||||
endif
|
||||
|
||||
|
|
@ -465,7 +465,7 @@ kernel_all.c: sources_list_updated ${C_SOURCES_WITH_PARSE} ${DOMAIN_CONFIG_FILE}
|
|||
|
||||
kernel.o: kernel_final.s
|
||||
@echo " [AS] $@"
|
||||
$(Q)${AS} ${ASFLAGS} -o $@ $<
|
||||
$(Q)${CC} ${ASFLAGS} -o $@ -c $<
|
||||
|
||||
kernel_final.s: kernel_final.c
|
||||
@echo " [CC] $@"
|
||||
|
|
@ -480,7 +480,7 @@ LINKER_SCRIPT = src/plat/${PLAT}/linker.lds
|
|||
|
||||
kernel.elf: ${OBJECTS} ${LINKER_SCRIPT}
|
||||
@echo " [LD] $@"
|
||||
$(Q)${CHANGED} $@ ${LD} ${LDFLAGS} -T ${SOURCE_ROOT}/${LINKER_SCRIPT} \
|
||||
$(Q)${CHANGED} $@ ${CC} ${LDFLAGS} -Wl,-T -Wl,${SOURCE_ROOT}/${LINKER_SCRIPT} \
|
||||
-o $@ ${OBJECTS}
|
||||
|
||||
############################################################
|
||||
|
|
@ -493,7 +493,7 @@ kernel.elf: ${OBJECTS} ${LINKER_SCRIPT}
|
|||
|
||||
%.o: %.s | ${DIRECTORIES}
|
||||
@echo " [AS] $@"
|
||||
$(Q)${AS} ${ASFLAGS} $< -o $@
|
||||
$(Q)${CC} ${ASFLAGS} -c $< -o $@
|
||||
|
||||
|
||||
###################
|
||||
|
|
|
|||
20
README.md
20
README.md
|
|
@ -13,15 +13,23 @@ The seL4 Repository
|
|||
|
||||
This repository contains the source code of seL4 microkernel.
|
||||
|
||||
For details about the seL4 microkernel, including details about the proof,
|
||||
please see the [`sel4.systems`][1] website and associated [FAQ][2].
|
||||
For details about the seL4 microkernel, including details about its formal
|
||||
correctness proof, please see the [`sel4.systems`][1] website and associated
|
||||
[FAQ][2].
|
||||
|
||||
DOIs for citing recent releases of this repository:
|
||||
* [![DOI][4]](http://dx.doi.org/10.5281/zenodo.11247)
|
||||
|
||||
We welcome contributions to seL4. Please see the website for information
|
||||
on [how to contribute][3].
|
||||
|
||||
This repository is usually not used in isolation, but as part of the build
|
||||
system in a larger project.
|
||||
|
||||
[1]: http://sel4.systems/
|
||||
[2]: http://sel4.systems/FAQ/
|
||||
|
||||
[3]: http://sel4.systems/Contributing/
|
||||
[4]: https://zenodo.org/badge/doi/10.5281/zenodo.11247.png
|
||||
|
||||
Repository Overview
|
||||
-------------------
|
||||
|
|
@ -31,7 +39,7 @@ Repository Overview
|
|||
* `haskell`: Haskell model of the seL4 kernel,
|
||||
kept in sync with the C version.
|
||||
* `libsel4`: C bindings for the seL4 ABI
|
||||
* `manual`: LaTeX sourced of the seL4 reference manual
|
||||
* `manual`: LaTeX sources of the seL4 reference manual
|
||||
|
||||
|
||||
Build Instructions
|
||||
|
|
@ -63,6 +71,10 @@ build using `make`, follow these instructions:
|
|||
|
||||
* For a debug build, append `DEBUG=y`.
|
||||
|
||||
See the seL4 website for more [comprehensive build instructions][5].
|
||||
|
||||
[5]: http://sel4.systems/Download/
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
|
|
|
|||
|
|
@ -138,6 +138,10 @@ The following data type defines the set of possible invocations for IRQ capabili
|
|||
> setIRQHandlerCap :: Capability,
|
||||
> setIRQHandlerSlot :: PPtr CTE }
|
||||
> | ClearIRQHandler { irqHandlerIRQ :: IRQ }
|
||||
> | SetMode {
|
||||
> modeIRQ :: IRQ,
|
||||
> modeTrigger :: Bool,
|
||||
> modePolarity :: Bool }
|
||||
> deriving Show
|
||||
|
||||
\subsection{Invocation Labels}
|
||||
|
|
@ -172,6 +176,7 @@ This datatype is defined globally over architectures as well as object types.
|
|||
> | IRQAckIRQ
|
||||
> | IRQSetIRQHandler
|
||||
> | IRQClearIRQHandler
|
||||
> | IRQSetMode
|
||||
> | DomainSetSet
|
||||
> | ARMPDClean_Data
|
||||
> | ARMPDInvalidate_Data
|
||||
|
|
|
|||
|
|
@ -554,12 +554,12 @@ If the kernel receives a VM fault from the CPU, it must determine the address an
|
|||
> handleVMFault _ ARMDataAbort = do
|
||||
> addr <- withoutFailure $ doMachineOp getFAR
|
||||
> fault <- withoutFailure $ doMachineOp getDFSR
|
||||
> throw $ VMFault addr [0, fault .&. mask 12]
|
||||
> throw $ VMFault addr [0, fault .&. mask 14]
|
||||
>
|
||||
> handleVMFault thread ARMPrefetchAbort = do
|
||||
> pc <- withoutFailure $ asUser thread $ getRestartPC
|
||||
> fault <- withoutFailure $ doMachineOp getIFSR
|
||||
> throw $ VMFault (VPtr pc) [1, fault .&. mask 12]
|
||||
> throw $ VMFault (VPtr pc) [1, fault .&. mask 14]
|
||||
|
||||
\subsection{Unmapping and Deletion}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,6 +156,12 @@ This function is used by the kernel to acknowledge an interrupt, after it has be
|
|||
> ackInterrupt :: IRQ -> MachineMonad ()
|
||||
> ackInterrupt (IRQ irq) = Arch.ackInterrupt irq
|
||||
|
||||
This function is used to implement IOAPIC functionality in the kernel.
|
||||
|
||||
> setInterruptMode :: IRQ -> Bool -> Bool -> MachineMonad ()
|
||||
> setInterruptMode (IRQ irq) levelTrigger polarityLow = Arch.setInterruptMode irq levelTrigger polarityLow
|
||||
|
||||
|
||||
\subsubsection{Timers}
|
||||
|
||||
The timer interval is set at boot time by calling this function. It returns the IRQ that is used for timer interrupts.
|
||||
|
|
|
|||
|
|
@ -142,6 +142,10 @@ The following functions define the ARM-specific interface between the kernel and
|
|||
> cbptr <- ask
|
||||
> liftIO $ Platform.maskInterrupt cbptr maskI irq
|
||||
|
||||
> -- IOAPIC only does stuff on IA32
|
||||
> setInterruptMode :: IRQ -> Bool -> Bool -> MachineMonad ()
|
||||
> setInterruptMode _ _ _ = return ()
|
||||
|
||||
> configureTimer :: MachineMonad IRQ
|
||||
> configureTimer = do
|
||||
> cbptr <- ask
|
||||
|
|
|
|||
|
|
@ -90,9 +90,9 @@ There is a single, global interrupt controller object; a capability to it is pro
|
|||
|
||||
An IRQ handler capability allows a thread possessing it to set an endpoint which will be notified of incoming interrupts, and to acknowledge received interrupts.
|
||||
|
||||
> decodeIRQHandlerInvocation :: Word -> IRQ -> [(Capability, PPtr CTE)] ->
|
||||
> decodeIRQHandlerInvocation :: Word -> [Word] -> IRQ -> [(Capability, PPtr CTE)] ->
|
||||
> KernelF SyscallError IRQHandlerInvocation
|
||||
> decodeIRQHandlerInvocation label irq extraCaps =
|
||||
> decodeIRQHandlerInvocation label args irq extraCaps =
|
||||
> case (invocationType label,extraCaps) of
|
||||
> (IRQAckIRQ,_) -> return $ AckIRQ irq
|
||||
> (IRQSetIRQHandler,(cap,slot):_) -> case cap of
|
||||
|
|
@ -101,8 +101,14 @@ An IRQ handler capability allows a thread possessing it to set an endpoint which
|
|||
> _ -> throw $ InvalidCapability 0
|
||||
> (IRQSetIRQHandler,_) -> throw TruncatedMessage
|
||||
> (IRQClearIRQHandler,_) -> return $ ClearIRQHandler irq
|
||||
> (IRQSetMode,_) -> case args of
|
||||
> trig:pol:_ -> return $ SetMode irq (toBool trig) (toBool pol)
|
||||
> _ -> throw TruncatedMessage
|
||||
> _ -> throw IllegalOperation
|
||||
|
||||
> toBool :: Word -> Bool
|
||||
> toBool w = w /= 0
|
||||
|
||||
> invokeIRQHandler :: IRQHandlerInvocation -> Kernel ()
|
||||
> invokeIRQHandler (AckIRQ irq) =
|
||||
> doMachineOp $ maskInterrupt False irq
|
||||
|
|
@ -113,6 +119,8 @@ An IRQ handler capability allows a thread possessing it to set an endpoint which
|
|||
> invokeIRQHandler (ClearIRQHandler irq) = do
|
||||
> irqSlot <- getIRQSlot irq
|
||||
> cteDeleteOne irqSlot
|
||||
> invokeIRQHandler (SetMode irq trig pol) =
|
||||
> doMachineOp $ setInterruptMode irq trig pol
|
||||
|
||||
\subsection{Kernel Functions}
|
||||
|
||||
|
|
|
|||
|
|
@ -452,9 +452,9 @@ The "decodeInvocation" function parses the message, determines the operation tha
|
|||
> liftM InvokeIRQControl $
|
||||
> decodeIRQControlInvocation label args slot $ map fst extraCaps
|
||||
>
|
||||
> decodeInvocation label _ _ _ (IRQHandlerCap { capIRQ = irq }) extraCaps =
|
||||
> decodeInvocation label args _ _ (IRQHandlerCap { capIRQ = irq }) extraCaps =
|
||||
> liftM InvokeIRQHandler $
|
||||
> decodeIRQHandlerInvocation label irq extraCaps
|
||||
> decodeIRQHandlerInvocation label args irq extraCaps
|
||||
>
|
||||
> decodeInvocation label args capIndex slot (ArchObjectCap cap) extraCaps =
|
||||
> liftM InvokeArchObject $
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ void setNextPC(tcb_t *thread, word_t v);
|
|||
/* Architecture specific machine operations */
|
||||
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline uint32_t getProcessorID(void)
|
||||
{
|
||||
uint32_t processor_id;
|
||||
|
|
@ -72,6 +73,7 @@ static inline uint32_t getProcessorID(void)
|
|||
return processor_id;
|
||||
}
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
static inline uint32_t readSystemControlRegister(void)
|
||||
{
|
||||
uint32_t scr;
|
||||
|
|
@ -79,11 +81,13 @@ static inline uint32_t readSystemControlRegister(void)
|
|||
return scr;
|
||||
}
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void writeSystemControlRegister(uint32_t scr)
|
||||
{
|
||||
MCR("p15, 0, %0, c1, c0, 0", scr);
|
||||
}
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
static inline uint32_t readAuxiliaryControlRegister(void)
|
||||
{
|
||||
uint32_t acr;
|
||||
|
|
@ -91,12 +95,14 @@ static inline uint32_t readAuxiliaryControlRegister(void)
|
|||
return acr;
|
||||
}
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void writeAuxiliaryControlRegister(uint32_t acr)
|
||||
{
|
||||
MCR("p15, 0, %0, c1, c0, 1", acr);
|
||||
}
|
||||
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void clearExMonitor(void)
|
||||
{
|
||||
word_t tmp;
|
||||
|
|
@ -104,12 +110,14 @@ static inline void clearExMonitor(void)
|
|||
}
|
||||
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void flushBTAC(void)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %0, c7, c5, 6" : : "r"(0));
|
||||
}
|
||||
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void writeContextID(word_t id)
|
||||
{
|
||||
#ifndef ARM_HYP
|
||||
|
|
@ -137,6 +145,7 @@ void setHardwareASID(hw_asid_t hw_asid);
|
|||
|
||||
/* Address space control */
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void setCurrentPD(paddr_t addr)
|
||||
{
|
||||
#ifndef ARM_HYP
|
||||
|
|
@ -203,6 +212,7 @@ static inline void setMAIR(word_t hmair0, word_t hmair1)
|
|||
|
||||
/* TLB control */
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void invalidateTLB(void)
|
||||
{
|
||||
dsb();
|
||||
|
|
@ -212,6 +222,7 @@ static inline void invalidateTLB(void)
|
|||
}
|
||||
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void invalidateTLB_ASID(hw_asid_t hw_asid)
|
||||
{
|
||||
#ifdef ARM_HYP
|
||||
|
|
@ -224,6 +235,7 @@ static inline void invalidateTLB_ASID(hw_asid_t hw_asid)
|
|||
#endif
|
||||
}
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void invalidateTLB_VAASID(word_t mva_plus_asid)
|
||||
{
|
||||
#ifdef ARM_HYP
|
||||
|
|
@ -248,6 +260,7 @@ static inline void invalidateHypTLB(void)
|
|||
void lockTLBEntry(vptr_t vaddr);
|
||||
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void cleanByVA(vptr_t vaddr, paddr_t paddr)
|
||||
{
|
||||
#ifdef ARM_CORTEX_A8
|
||||
|
|
@ -284,6 +297,7 @@ static inline void cleanByVA_PoU(vptr_t vaddr, paddr_t paddr)
|
|||
}
|
||||
/* D-Cache invalidate to PoC (v6/v7 common) */
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void invalidateByVA(vptr_t vaddr, paddr_t paddr)
|
||||
{
|
||||
#ifdef ARM_CORTEX_A8
|
||||
|
|
@ -296,6 +310,7 @@ static inline void invalidateByVA(vptr_t vaddr, paddr_t paddr)
|
|||
dmb();
|
||||
}
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
/* I-Cache invalidate to PoU (L2 cache) (v6/v7 common) */
|
||||
static inline void invalidateByVA_I(vptr_t vaddr, paddr_t paddr)
|
||||
{
|
||||
|
|
@ -308,6 +323,7 @@ static inline void invalidateByVA_I(vptr_t vaddr, paddr_t paddr)
|
|||
isb();
|
||||
}
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
/* I-Cache invalidate all to PoU (L2 cache) (v6/v7 common) */
|
||||
static inline void invalidate_I_PoU(void)
|
||||
{
|
||||
|
|
@ -319,6 +335,7 @@ static inline void invalidate_I_PoU(void)
|
|||
isb();
|
||||
}
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
/* D-Cache clean & invalidate to PoC (v6/v7 common) */
|
||||
static inline void cleanInvalByVA(vptr_t vaddr, paddr_t paddr)
|
||||
{
|
||||
|
|
@ -334,6 +351,7 @@ static inline void cleanInvalByVA(vptr_t vaddr, paddr_t paddr)
|
|||
dsb();
|
||||
}
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
/* Invalidate branch predictors by VA (v6/v7 common) */
|
||||
static inline void branchFlush(vptr_t vaddr, paddr_t paddr)
|
||||
{
|
||||
|
|
@ -364,6 +382,7 @@ void cleanInvalidateL1Caches(void);
|
|||
|
||||
/* Fault status */
|
||||
/** MODIFIES: */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline word_t PURE getIFSR(void)
|
||||
{
|
||||
word_t IFSR;
|
||||
|
|
@ -371,6 +390,7 @@ static inline word_t PURE getIFSR(void)
|
|||
return IFSR;
|
||||
}
|
||||
/** MODIFIES: */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline word_t PURE getDFSR(void)
|
||||
{
|
||||
word_t DFSR;
|
||||
|
|
@ -378,6 +398,7 @@ static inline word_t PURE getDFSR(void)
|
|||
return DFSR;
|
||||
}
|
||||
/** MODIFIES: */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline word_t PURE getFAR(void)
|
||||
{
|
||||
word_t FAR;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ bool_t isIRQPending(void);
|
|||
void maskInterrupt(bool_t disable, interrupt_t irq);
|
||||
/** MODIFIES: [*] */
|
||||
void ackInterrupt(irq_t irq);
|
||||
/** MODIFIES: [*] */
|
||||
static inline void setInterruptMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow) { }
|
||||
|
||||
/** MODIFIES: [*] */
|
||||
void initIRQController(void);
|
||||
|
|
|
|||
|
|
@ -375,9 +375,9 @@ block vm_fault {
|
|||
padding 2
|
||||
field instructionFault 1
|
||||
#else
|
||||
field FSR 12
|
||||
field FSR 14
|
||||
field instructionFault 1
|
||||
padding 16
|
||||
padding 14
|
||||
#endif
|
||||
field faultType 3
|
||||
}
|
||||
|
|
@ -684,6 +684,7 @@ tagged_union pteS1 pteS1Type {
|
|||
#endif /* !ARM_HYP */
|
||||
|
||||
-- VM attributes
|
||||
|
||||
block vm_attributes {
|
||||
padding 30
|
||||
field armParityEnabled 1
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#include <plat/machine/hardware.h>
|
||||
#include <arch/machine.h>
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void dsb_fp(void)
|
||||
{
|
||||
/*
|
||||
|
|
@ -31,6 +32,7 @@ static inline void dsb_fp(void)
|
|||
}
|
||||
|
||||
/* Change the translation root by updating TTBR0. */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void
|
||||
setCurrentPD_fp(word_t pd_addr)
|
||||
{
|
||||
|
|
@ -43,6 +45,7 @@ setCurrentPD_fp(word_t pd_addr)
|
|||
}
|
||||
|
||||
/* Change the current hardware ASID. */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void
|
||||
setHardwareASID_fp(hw_asid_t asid)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -12,18 +12,21 @@
|
|||
#define __ARCH_ARMV6_MACHINE_H
|
||||
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void dsb(void)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %0, c7, c10, 4" : : "r"(0) : "memory");
|
||||
}
|
||||
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void dmb(void)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory");
|
||||
}
|
||||
|
||||
/** MODIFIES: [*] */
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void isb(void)
|
||||
{
|
||||
asm volatile("mcr p15, 0, %0, c7, c5, 4" : : "r"(0) : "memory");
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include <api/syscall.h>
|
||||
|
||||
void slowpath(syscall_t syscall)
|
||||
VISIBLE FASTCALL NORETURN;
|
||||
NORETURN;
|
||||
|
||||
void fastpath_call(word_t cptr, word_t r_msgInfo)
|
||||
VISIBLE FASTCALL NORETURN;
|
||||
|
|
|
|||
|
|
@ -24,6 +24,10 @@ bool_t map_kernel_window(
|
|||
pde_t* pd,
|
||||
pte_t* pt,
|
||||
p_region_t ndks_p_reg
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
, uint32_t num_ioapic,
|
||||
paddr_t* ioapic_paddrs
|
||||
#endif
|
||||
#ifdef CONFIG_IOMMU
|
||||
, uint32_t num_drhu,
|
||||
paddr_t* drhu_list
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
/* maximum number of device regions in bootinfo */
|
||||
/* WARNING: must match value in libsel4! */
|
||||
#ifndef CONFIG_MAX_NUM_BOOTINFO_DEVICE_REGIONS
|
||||
#define CONFIG_MAX_NUM_BOOTINFO_DEVICE_REGIONS 200
|
||||
#define CONFIG_MAX_NUM_BOOTINFO_DEVICE_REGIONS 199
|
||||
#endif
|
||||
|
||||
/* maximum number of untyped caps in bootinfo */
|
||||
|
|
|
|||
|
|
@ -21,11 +21,12 @@ exception_t decodeIRQControlInvocation(word_t label, unsigned int length,
|
|||
cte_t *srcSlot, extra_caps_t extraCaps,
|
||||
word_t *buffer);
|
||||
exception_t invokeIRQControl(irq_t irq, cte_t *handlerSlot, cte_t *controlSlot);
|
||||
exception_t decodeIRQHandlerInvocation(word_t label, irq_t irq,
|
||||
extra_caps_t extraCaps);
|
||||
exception_t decodeIRQHandlerInvocation(word_t label, unsigned int length, irq_t irq,
|
||||
extra_caps_t extraCaps, word_t *buffer);
|
||||
void invokeIRQHandler_AckIRQ(irq_t irq);
|
||||
void invokeIRQHandler_SetIRQHandler(irq_t irq, cap_t cap, cte_t *slot);
|
||||
void invokeIRQHandler_ClearIRQHandler(irq_t irq);
|
||||
void invokeIRQHandler_SetMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow);
|
||||
void deletingIRQHandler(irq_t irq);
|
||||
void deletedIRQHandler(irq_t irq);
|
||||
void handleInterrupt(irq_t irq);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ void maskInterrupt(bool_t enable, irq_t irq);
|
|||
/** MODIFIES: */
|
||||
irq_t getActiveIRQ(void);
|
||||
/** MODIFIES: [*] */
|
||||
static inline void setInterruptMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow) { }
|
||||
/** MODIFIES: [*] */
|
||||
void resetTimer(void);
|
||||
/** MODIFIES: [*] */
|
||||
void initTimer(void);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ void maskInterrupt(bool_t enable, irq_t irq);
|
|||
/** MODIFIES: */
|
||||
irq_t getActiveIRQ(void);
|
||||
/** MODIFIES: [*] */
|
||||
static inline void setInterruptMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow) { }
|
||||
/** MODIFIES: [*] */
|
||||
void resetTimer(void);
|
||||
/** MODIFIES: [*] */
|
||||
void initTimer(void);
|
||||
|
|
|
|||
|
|
@ -72,6 +72,8 @@ void maskInterrupt(bool_t enable, irq_t irq);
|
|||
/** MODIFIES: */
|
||||
irq_t getActiveIRQ(void);
|
||||
/** MODIFIES: [*] */
|
||||
static inline void setInterruptMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow) { }
|
||||
/** MODIFIES: [*] */
|
||||
void resetTimer(void);
|
||||
/** MODIFIES: [*] */
|
||||
void initTimer(void);
|
||||
|
|
|
|||
|
|
@ -11,37 +11,60 @@
|
|||
#ifndef __PLAT_MACHINE_H
|
||||
#define __PLAT_MACHINE_H
|
||||
|
||||
/* interrupt vectors (corresponds to IDT entries) */
|
||||
#define PIC_IRQ_LINES 16
|
||||
#define IOAPIC_IRQ_LINES 24
|
||||
|
||||
typedef enum _interrupt_t {
|
||||
int_invalid = -1,
|
||||
int_unimpl_dev = 0x07,
|
||||
int_page_fault = 0x0e,
|
||||
int_irq_min = 0x20, /* First IRQ. */
|
||||
int_irq_isa_min = 0x20,
|
||||
int_irq_isa_max = 0x2f,
|
||||
int_irq_msi_min = 0x30,
|
||||
int_irq_msi_max = 0x3d,
|
||||
int_iommu = 0x3e,
|
||||
int_timer = 0x3f,
|
||||
int_irq_max = 0x3f, /* Last IRQ. */
|
||||
int_trap_min = 0x40,
|
||||
int_trap_max = 0xfe,
|
||||
int_spurious = 0xff,
|
||||
int_max = 0xff
|
||||
} interrupt_t;
|
||||
/* interrupt vectors (corresponds to IDT entries) */
|
||||
|
||||
#define IRQ_INT_OFFSET 0x20
|
||||
|
||||
typedef enum _interrupt_t {
|
||||
int_invalid = -1,
|
||||
int_unimpl_dev = 0x07,
|
||||
int_page_fault = 0x0e,
|
||||
int_irq_min = IRQ_INT_OFFSET, /* First IRQ. */
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
int_irq_ioapic_min = int_irq_min,
|
||||
int_irq_ioapic_max = (int_irq_ioapic_min + (CONFIG_MAX_NUM_IOAPIC * IOAPIC_IRQ_LINES)) - 1,
|
||||
#else
|
||||
int_irq_isa_min = int_irq_min,
|
||||
int_irq_isa_max = int_irq_min + PIC_IRQ_LINES - 1,
|
||||
#endif
|
||||
int_irq_msi_min,
|
||||
int_irq_msi_max = int_irq_msi_min + 0xd,
|
||||
int_iommu,
|
||||
int_timer,
|
||||
int_irq_max = int_timer, /* Last IRQ. */
|
||||
int_trap_min,
|
||||
int_trap_max = 0xfe,
|
||||
int_spurious = 0xff,
|
||||
int_max = 0xff
|
||||
} interrupt_t;
|
||||
|
||||
/* Construction of most of the interrupt numbers was relative by padding
|
||||
* off previous values. Therefore to ensure we didn't overflow just need
|
||||
* to ensure int_trap_min is less than int_trap_max */
|
||||
compile_assert(interrupt_numbers_not_overflow, int_trap_min < int_trap_max);
|
||||
|
||||
|
||||
typedef enum _irq_t {
|
||||
irqInvalid = -1,
|
||||
irq_isa_min = int_irq_isa_min - IRQ_INT_OFFSET, /* 0x00 */
|
||||
irq_isa_max = int_irq_isa_max - IRQ_INT_OFFSET, /* 0x0f */
|
||||
irq_msi_min = int_irq_msi_min - IRQ_INT_OFFSET, /* 0x10 */
|
||||
irq_msi_max = int_irq_msi_max - IRQ_INT_OFFSET, /* 0x1d */
|
||||
irq_iommu = int_iommu - IRQ_INT_OFFSET, /* 0x1e */
|
||||
irq_timer = int_timer - IRQ_INT_OFFSET, /* 0x1f */
|
||||
maxIRQ = int_timer - IRQ_INT_OFFSET /* 0x1f */
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
irq_ioapic_min = int_irq_ioapic_min - IRQ_INT_OFFSET,
|
||||
irq_controller_min = irq_ioapic_min,
|
||||
irq_ioapic_max = int_irq_ioapic_max - IRQ_INT_OFFSET,
|
||||
irq_controller_max = irq_ioapic_max,
|
||||
#else
|
||||
irq_isa_min = int_irq_isa_min - IRQ_INT_OFFSET,
|
||||
irq_controller_min = irq_isa_min,
|
||||
irq_isa_max = int_irq_isa_max - IRQ_INT_OFFSET,
|
||||
irq_controller_max = irq_isa_max,
|
||||
#endif
|
||||
irq_msi_min = int_irq_msi_min - IRQ_INT_OFFSET,
|
||||
irq_msi_max = int_irq_msi_max - IRQ_INT_OFFSET,
|
||||
irq_iommu = int_iommu - IRQ_INT_OFFSET,
|
||||
irq_timer = int_timer - IRQ_INT_OFFSET,
|
||||
maxIRQ = int_timer - IRQ_INT_OFFSET
|
||||
} irq_t;
|
||||
|
||||
#define BIOS_PADDR_START 0x0e0000
|
||||
|
|
|
|||
|
|
@ -42,7 +42,9 @@ acpi_rsdt_t* acpi_init(void);
|
|||
uint32_t acpi_madt_scan(
|
||||
acpi_rsdt_t* acpi_rsdt,
|
||||
cpu_id_t* cpu_list,
|
||||
uint32_t max_list_len
|
||||
uint32_t max_list_len,
|
||||
uint32_t* num_ioapic,
|
||||
paddr_t* ioapic_addrs
|
||||
);
|
||||
|
||||
#ifdef CONFIG_IOMMU
|
||||
|
|
|
|||
|
|
@ -16,8 +16,17 @@
|
|||
|
||||
#define PPTR_APIC PPTR_KDEV
|
||||
|
||||
#ifdef CONFIG_IOMMU
|
||||
/* Whether the IOAPIC exists or not will determine where we start mapping
|
||||
* the IOMMUs. It is fine to define the DRHU_START even if CONFIG_IOMMU is not
|
||||
* set as it will just pollute the preprocessor namespace */
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
#define PPTR_IOAPIC_START (PPTR_APIC + BIT(PAGE_BITS))
|
||||
#define PPTR_DRHU_START (PPTR_IOAPIC_START + BIT(PAGE_BITS) * CONFIG_MAX_NUM_IOAPIC)
|
||||
#else /* CONFIG_IOAPIC */
|
||||
#define PPTR_DRHU_START (PPTR_APIC + BIT(PAGE_BITS))
|
||||
#endif /* CONFIG_IOAPIC */
|
||||
|
||||
#ifdef CONFIG_IOMMU
|
||||
#define MAX_NUM_DRHU ((-PPTR_DRHU_START) >> PAGE_BITS)
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ void maskInterrupt(bool_t mask, irq_t irq);
|
|||
void ackInterrupt(irq_t irq);
|
||||
irq_t getActiveIRQ(void);
|
||||
bool_t isIRQPending(void);
|
||||
void setInterruptMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow);
|
||||
void resetTimer(void);
|
||||
void platAddDevices(void);
|
||||
|
||||
|
|
|
|||
26
include/plat/pc99/plat/machine/ioapic.h
Normal file
26
include/plat/pc99/plat/machine/ioapic.h
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2014, General Dynamics C4 Systems
|
||||
*
|
||||
* This software may be distributed and modified according to the terms of
|
||||
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
|
||||
* See "LICENSE_GPLv2.txt" for details.
|
||||
*
|
||||
* @TAG(GD_GPL)
|
||||
*/
|
||||
|
||||
#ifndef __PLAT_MACHINE_IOAPIC_H
|
||||
#define __PLAT_MACHINE_IOAPIC_H
|
||||
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
|
||||
#include <types.h>
|
||||
#include <plat/machine.h>
|
||||
#include <arch/types.h>
|
||||
|
||||
void ioapic_init(uint32_t num_nodes, cpu_id_t *cpu_list, uint32_t num_ioapic);
|
||||
void ioapic_mask_irq(bool_t mask, irq_t irq);
|
||||
void ioapic_set_mode(irq_t irq, bool_t levelTrigger, bool_t polarityLow);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -14,9 +14,17 @@
|
|||
#include <types.h>
|
||||
#include <plat/machine.h>
|
||||
|
||||
/* Even if not using the PIC as the main interrupt controller we still
|
||||
* need to interact with it to remap and disable it */
|
||||
void pic_remap_irqs(interrupt_t vector);
|
||||
void pic_disable(void);
|
||||
|
||||
#ifdef CONFIG_IRQ_PIC
|
||||
|
||||
void pic_mask_irq(bool_t mask, irq_t irq);
|
||||
bool_t pic_is_irq_pending(void);
|
||||
void pic_ack_active_irq(void);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -29,8 +29,16 @@
|
|||
* programming the device */
|
||||
#define IRQ_OFFSET 0x20
|
||||
|
||||
/* Range for MSI irqs */
|
||||
/* Range for MSI irqs. Currently no proper way of getting at the corresponding
|
||||
* definition inside seL4, but the vector table is setup such that MSIs start
|
||||
* after all the IRQs for the external interrupt controller (PIC or IOAPIC).
|
||||
* PIC has 0x10 lines and for the IOAPIC there are 24 for each IOAPIC */
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
#define MSI_MIN (24 * CONFIG_MAX_NUM_IOAPIC)
|
||||
#define MSI_MAX (MSI_MIN + 0xd)
|
||||
#else
|
||||
#define MSI_MIN 0x10
|
||||
#define MSI_MAX 0x1d
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -145,6 +145,10 @@
|
|||
<param dir="in" name="endpoint" type="seL4_CPtr"/>
|
||||
</method>
|
||||
<method id="IRQClearIRQHandler" name="Clear"/>
|
||||
<method id="IRQSetMode" name="SetMode">
|
||||
<param dir="in" name="level_trigger" type="uint32_t"/>
|
||||
<param dir="in" name="low_polarity" type="uint32_t"/>
|
||||
</method>
|
||||
</interface>
|
||||
<interface name="seL4_DomainSet">
|
||||
<method id="DomainSetSet" name="Set">
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2014, NICTA
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2014, NICTA
|
||||
#
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <arch/machine/hardware.h>
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
void
|
||||
clean_D_PoU(void)
|
||||
{
|
||||
|
|
@ -17,6 +18,7 @@ clean_D_PoU(void)
|
|||
asm volatile("mcr p15, 0, %0, c7, c10, 0" : : "r"(0));
|
||||
}
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
void
|
||||
cleanInvalidate_D_PoC(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ lookup_fp(cap_t cap, cptr_t cptr)
|
|||
return cap;
|
||||
}
|
||||
|
||||
/** DONT_TRANSLATE */
|
||||
static inline void
|
||||
clearExMonitor_fp(void)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -446,6 +446,12 @@ try_init_kernel(
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Before creating the initial thread (which also switches to it)
|
||||
* we clean the cache so that any page table information written
|
||||
* as a result of calling create_frames_of_region will be correctly
|
||||
* read by the hardware page table walker */
|
||||
cleanInvalidateL1Caches();
|
||||
|
||||
/* create the initial thread */
|
||||
if (!create_initial_thread(
|
||||
root_cnode_cap,
|
||||
|
|
|
|||
|
|
@ -2096,11 +2096,13 @@ decodeARMFrameInvocation(word_t label, unsigned int length,
|
|||
}
|
||||
}
|
||||
|
||||
static const resolve_ret_t default_resolve_ret_t;
|
||||
|
||||
static resolve_ret_t
|
||||
resolveVAddr(pde_t *pd, vptr_t vaddr)
|
||||
{
|
||||
pde_t *pde = lookupPDSlot(pd, vaddr);
|
||||
resolve_ret_t ret;
|
||||
resolve_ret_t ret = default_resolve_ret_t;
|
||||
|
||||
ret.valid = true;
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ include ${SOURCE_ROOT}/src/arch/$(ARCH)/model/Makefile
|
|||
include ${SOURCE_ROOT}/src/arch/$(ARCH)/machine/Makefile
|
||||
include ${SOURCE_ROOT}/src/arch/$(ARCH)/fastpath/Makefile
|
||||
|
||||
ARCH_C_SOURCES += c_traps.c
|
||||
|
||||
ARCH_ASM_SOURCES += machine_asm.S \
|
||||
traps.S \
|
||||
halt.S \
|
||||
|
|
|
|||
171
src/arch/ia32/c_traps.c
Normal file
171
src/arch/ia32/c_traps.c
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright 2014, General Dynamics C4 Systems
|
||||
*
|
||||
* This software may be distributed and modified according to the terms of
|
||||
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
|
||||
* See "LICENSE_GPLv2.txt" for details.
|
||||
*
|
||||
* @TAG(GD_GPL)
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <model/statedata.h>
|
||||
#include <arch/kernel/lock.h>
|
||||
#include <arch/machine/fpu.h>
|
||||
#include <arch/fastpath/fastpath.h>
|
||||
|
||||
#include <api/syscall.h>
|
||||
|
||||
void __attribute__((noreturn)) __attribute__((externally_visible)) restore_user_context(void);
|
||||
void __attribute__((noreturn)) __attribute__((externally_visible)) restore_user_context(void)
|
||||
{
|
||||
/* set the tss.esp0 */
|
||||
tss_ptr_set_esp0(&ia32KStss, ((uint32_t)ksCurThread) + 0x4c);
|
||||
if (unlikely(ksCurThread == ia32KSfpuOwner)) {
|
||||
/* We are using the FPU, make sure it is enabled */
|
||||
enableFpu();
|
||||
} else if (unlikely(ia32KSfpuOwner)) {
|
||||
/* Someone is using the FPU and it might be enabled */
|
||||
disableFpu();
|
||||
} else {
|
||||
/* No-one (including us) is using the FPU, so we assume it
|
||||
* is currently disabled */
|
||||
}
|
||||
/* see if we entered via syscall */
|
||||
if (likely(ksCurThread->tcbContext.registers[Error] == -1)) {
|
||||
ksCurThread->tcbContext.registers[EFLAGS] &= ~0x200;
|
||||
asm volatile(
|
||||
// Set our stack pointer to the top of the tcb so we can efficiently pop
|
||||
"movl %0, %%esp\n"
|
||||
// restore syscall number
|
||||
"popl %%eax\n"
|
||||
// cap/badge reigster
|
||||
"popl %%ebx\n"
|
||||
// skip ecx and edx, these will contain esp and nexteip due to sysenter/sysexit convention
|
||||
"addl $8, %%esp\n"
|
||||
// message info register
|
||||
"popl %%esi\n"
|
||||
// message register
|
||||
"popl %%edi\n"
|
||||
// message register
|
||||
"popl %%ebp\n"
|
||||
//ds (if changed)
|
||||
"cmpl $0x23, (%%esp)\n"
|
||||
"je 1f\n"
|
||||
"popl %%ds\n"
|
||||
"jmp 2f\n"
|
||||
"1: addl $4, %%esp\n"
|
||||
"2:\n"
|
||||
//es (if changed)
|
||||
"cmpl $0x23, (%%esp)\n"
|
||||
"je 1f\n"
|
||||
"popl %%es\n"
|
||||
"jmp 2f\n"
|
||||
"1: addl $4, %%esp\n"
|
||||
"2:\n"
|
||||
//have to reload other selectors
|
||||
"popl %%fs\n"
|
||||
"popl %%gs\n"
|
||||
// skip faulteip, tls_base and error (these are fake registers)
|
||||
"addl $12, %%esp\n"
|
||||
// restore nexteip
|
||||
"popl %%edx\n"
|
||||
// skip cs
|
||||
"addl $4, %%esp\n"
|
||||
"popfl\n"
|
||||
// reset interrupt bit
|
||||
"orl $0x200, -4(%%esp)\n"
|
||||
// restore esp
|
||||
"pop %%ecx\n"
|
||||
"sti\n"
|
||||
"sysexit\n"
|
||||
:
|
||||
: "r"(&ksCurThread->tcbContext.registers[EAX])
|
||||
// Clobber memory so the compiler is forced to complete all stores
|
||||
// before running this assembler
|
||||
: "memory"
|
||||
);
|
||||
} else {
|
||||
asm volatile(
|
||||
// Set our stack pointer to the top of the tcb so we can efficiently pop
|
||||
"movl %0, %%esp\n"
|
||||
"popl %%eax\n"
|
||||
"popl %%ebx\n"
|
||||
"popl %%ecx\n"
|
||||
"popl %%edx\n"
|
||||
"popl %%esi\n"
|
||||
"popl %%edi\n"
|
||||
"popl %%ebp\n"
|
||||
"popl %%ds\n"
|
||||
"popl %%es\n"
|
||||
"popl %%fs\n"
|
||||
"popl %%gs\n"
|
||||
// skip faulteip, tls_base, error
|
||||
"addl $12, %%esp\n"
|
||||
"iret\n"
|
||||
:
|
||||
: "r"(&ksCurThread->tcbContext.registers[EAX])
|
||||
// Clobber memory so the compiler is forced to complete all stores
|
||||
// before running this assembler
|
||||
: "memory"
|
||||
);
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
void __attribute__((fastcall)) __attribute__((externally_visible)) c_handle_interrupt(int irq, int syscall);
|
||||
void __attribute__((fastcall)) __attribute__((externally_visible)) c_handle_interrupt(int irq, int syscall)
|
||||
{
|
||||
if (irq == int_unimpl_dev) {
|
||||
handleUnimplementedDevice();
|
||||
} else if (irq == int_page_fault) {
|
||||
/* Error code is in Error. Pull out bit 5, which is whether it was instruction or data */
|
||||
handleVMFaultEvent((ksCurThread->tcbContext.registers[Error] >> 4) & 1);
|
||||
} else if (irq < int_irq_min) {
|
||||
handleUserLevelFault(irq, ksCurThread->tcbContext.registers[Error]);
|
||||
} else if (likely(irq < int_trap_min)) {
|
||||
ia32KScurInterrupt = irq;
|
||||
handleInterruptEntry();
|
||||
} else if (irq == int_spurious) {
|
||||
/* fall through to restore_user_context and do nothing */
|
||||
} else {
|
||||
/* Interpret a trap as an unknown syscall */
|
||||
/* Adjust FaultEIP to point to trapping INT
|
||||
* instruction by subtracting 2 */
|
||||
int sys_num;
|
||||
ksCurThread->tcbContext.registers[FaultEIP] -= 2;
|
||||
/* trap number is MSBs of the syscall number and the LSBS of EAX */
|
||||
sys_num = (irq << 24) | (syscall & 0x00ffffff);
|
||||
handleUnknownSyscall(sys_num);
|
||||
}
|
||||
restore_user_context();
|
||||
}
|
||||
|
||||
void __attribute__((noreturn))
|
||||
slowpath(syscall_t syscall)
|
||||
{
|
||||
ia32KScurInterrupt = -1;
|
||||
/* increment nextEIP to skip sysenter */
|
||||
ksCurThread->tcbContext.registers[NextEIP] += 2;
|
||||
/* check for undefined syscall */
|
||||
if (unlikely(syscall < SYSCALL_MIN || syscall > SYSCALL_MAX)) {
|
||||
handleUnknownSyscall(syscall);
|
||||
} else {
|
||||
handleSyscall(syscall);
|
||||
}
|
||||
restore_user_context();
|
||||
}
|
||||
|
||||
void __attribute__((externally_visible)) c_handle_syscall(syscall_t syscall, word_t cptr, word_t msgInfo);
|
||||
void __attribute__((externally_visible)) c_handle_syscall(syscall_t syscall, word_t cptr, word_t msgInfo)
|
||||
{
|
||||
#ifdef FASTPATH
|
||||
if (syscall == SysCall) {
|
||||
fastpath_call(cptr, msgInfo);
|
||||
} else if (syscall == SysReplyWait) {
|
||||
fastpath_reply_wait(cptr, msgInfo);
|
||||
}
|
||||
#endif
|
||||
|
||||
slowpath(syscall);
|
||||
}
|
||||
|
|
@ -34,19 +34,24 @@ extern uint32_t kernel_pd_list[CONFIG_MAX_NUM_NODES][BIT(PD_BITS)];
|
|||
/* functions exactly corresponding to abstract specification */
|
||||
|
||||
BOOT_CODE static void
|
||||
init_irqs(cap_t root_cnode_cap, bool_t mask_legacy_irqs)
|
||||
init_irqs(cap_t root_cnode_cap, bool_t mask_irqs)
|
||||
{
|
||||
irq_t i;
|
||||
|
||||
for (i = 0; i <= maxIRQ; i++) {
|
||||
if (i == irq_timer) {
|
||||
setIRQState(IRQTimer, i);
|
||||
} else if (i == irq_iommu || i == 2 /* cascaded legacy PIC */) {
|
||||
} else if (i == irq_iommu) {
|
||||
setIRQState(IRQReserved, i);
|
||||
} else if (i >= irq_isa_min && i <= irq_isa_max)
|
||||
if (mask_legacy_irqs)
|
||||
#ifdef CONFIG_IRQ_PIC
|
||||
} else if (i == 2) {
|
||||
/* cascaded legacy PIC */
|
||||
setIRQState(IRQReserved, i);
|
||||
#endif
|
||||
} else if (i >= irq_controller_min && i <= irq_controller_max)
|
||||
if (mask_irqs)
|
||||
/* Don't use setIRQState() here because it implicitly also enables */
|
||||
/* the IRQ on the PIC which only node 0 is allowed to do. */
|
||||
/* the IRQ on the interrupt controller which only node 0 is allowed to do. */
|
||||
{
|
||||
intStateIRQTable[i] = IRQReserved;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
#include <plat/machine/devices.h>
|
||||
#include <plat/machine/pci.h>
|
||||
#include <plat/machine/pic.h>
|
||||
#include <plat/machine/ioapic.h>
|
||||
|
||||
/* addresses defined in linker script */
|
||||
/* need a fake array to get the pointer from the linker script */
|
||||
|
|
@ -70,6 +71,8 @@ typedef struct glks {
|
|||
ui_info_t ui_info_list [CONFIG_MAX_NUM_NODES]; /* info about userland images */
|
||||
dev_p_regs_t dev_p_regs; /* device memory regions */
|
||||
uint32_t apic_khz; /* frequency of APIC/bus */
|
||||
uint32_t num_ioapic; /* number of IOAPICs detected */
|
||||
paddr_t ioapic_paddr[CONFIG_MAX_NUM_IOAPIC];
|
||||
#ifdef CONFIG_IOMMU
|
||||
uint32_t num_drhu; /* number of IOMMUs */
|
||||
paddr_t drhu_list[MAX_NUM_DRHU]; /* list of physical addresses of the IOMMUs */
|
||||
|
|
@ -293,6 +296,10 @@ lift_ndks(node_id_t node_id)
|
|||
(pde_t*)kernel_pd_list[node_id],
|
||||
(pte_t*)kernel_pt_list[node_id],
|
||||
ndks_p_reg
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
, glks.num_ioapic,
|
||||
glks.ioapic_paddr
|
||||
#endif
|
||||
#ifdef CONFIG_IOMMU
|
||||
, node_id == 0 ? glks.num_drhu : 0,
|
||||
glks.drhu_list
|
||||
|
|
@ -362,7 +369,11 @@ try_boot_node(void)
|
|||
/* initialise the CPU */
|
||||
if (!init_node_cpu(
|
||||
glks.apic_khz,
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
1
|
||||
#else
|
||||
node_id != 0
|
||||
#endif
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -464,6 +475,11 @@ try_boot_sys(
|
|||
|
||||
/* remapping legacy IRQs to their correct vectors */
|
||||
pic_remap_irqs(IRQ_INT_OFFSET);
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
/* Disable the PIC so that it does not generate any interrupts. We need to
|
||||
* do this *before* we initialize the apic */
|
||||
pic_disable();
|
||||
#endif
|
||||
|
||||
/* Prepare for accepting device regions from here on */
|
||||
glks.dev_p_regs.count = 0;
|
||||
|
|
@ -492,11 +508,21 @@ try_boot_sys(
|
|||
#endif
|
||||
|
||||
/* query available CPUs from ACPI */
|
||||
glks.num_nodes = acpi_madt_scan(acpi_rsdt, glks.cpu_list, CONFIG_MAX_NUM_NODES);
|
||||
glks.num_nodes = acpi_madt_scan(acpi_rsdt, glks.cpu_list, CONFIG_MAX_NUM_NODES, &glks.num_ioapic, glks.ioapic_paddr);
|
||||
if (glks.num_nodes == 0) {
|
||||
printf("No CPUs detected\n");
|
||||
return false;
|
||||
}
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
if (glks.num_ioapic == 0) {
|
||||
printf("No IOAPICs detected\n");
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
if (glks.num_ioapic > 0) {
|
||||
printf("Detected %d IOAPICs, but configured to use PIC instead\n", glks.num_ioapic);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (glks.num_nodes > cmdline_opt.max_num_nodes) {
|
||||
glks.num_nodes = cmdline_opt.max_num_nodes;
|
||||
|
|
@ -603,6 +629,11 @@ try_boot_sys(
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
/* Now that NDKS have been lifted we can access the IOAPIC and program it */
|
||||
ioapic_init(glks.num_nodes, glks.cpu_list, glks.num_ioapic);
|
||||
#endif
|
||||
|
||||
/* start up other CPUs and initialise their nodes */
|
||||
for (i = 1; i < glks.num_nodes; i++) {
|
||||
printf("Starting node #%d\n", i);
|
||||
|
|
|
|||
|
|
@ -575,6 +575,10 @@ map_kernel_window(
|
|||
pde_t* pd,
|
||||
pte_t* pt,
|
||||
p_region_t ndks_p_reg
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
, uint32_t num_ioapic,
|
||||
paddr_t* ioapic_paddrs
|
||||
#endif
|
||||
#ifdef CONFIG_IOMMU
|
||||
, uint32_t num_drhu,
|
||||
paddr_t* drhu_list
|
||||
|
|
@ -585,9 +589,7 @@ map_kernel_window(
|
|||
uint32_t idx;
|
||||
pde_t pde;
|
||||
pte_t pte;
|
||||
#ifdef CONFIG_IOMMU
|
||||
unsigned int i;
|
||||
#endif
|
||||
unsigned int UNUSED i;
|
||||
|
||||
/* Mapping of PPTR_BASE (virtual address) to kernel's PADDR_BASE
|
||||
* up to end of virtual address space except for the last 4M.
|
||||
|
|
@ -730,6 +732,49 @@ map_kernel_window(
|
|||
pt[idx] = pte;
|
||||
idx++;
|
||||
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
for (i = 0; i < num_ioapic; i++) {
|
||||
phys = ioapic_paddrs[i];
|
||||
pte = pte_new(
|
||||
phys, /* page_base_address */
|
||||
0, /* avl */
|
||||
1, /* global */
|
||||
0, /* pat */
|
||||
0, /* dirty */
|
||||
0, /* accessed */
|
||||
1, /* cache_disabled */
|
||||
1, /* write_through */
|
||||
0, /* super_user */
|
||||
1, /* read_write */
|
||||
1 /* present */
|
||||
);
|
||||
assert(idx == ( (PPTR_IOAPIC_START + i * BIT(pageBitsForSize(IA32_4K))) & MASK(pageBitsForSize(IA32_4M))) >> pageBitsForSize(IA32_4K));
|
||||
pt[idx] = pte;
|
||||
idx++;
|
||||
if (idx == BIT(PT_BITS)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/* put in null mappings for any extra IOAPICs */
|
||||
for (; i < CONFIG_MAX_NUM_IOAPIC; i++) {
|
||||
pte = pte_new(
|
||||
0, /* page_base_address */
|
||||
0, /* avl */
|
||||
0, /* global */
|
||||
0, /* pat */
|
||||
0, /* dirty */
|
||||
0, /* accessed */
|
||||
0, /* cache_disabled */
|
||||
0, /* write_through */
|
||||
0, /* super_user */
|
||||
0, /* read_write */
|
||||
0 /* present */
|
||||
);
|
||||
assert(idx == ( (PPTR_IOAPIC_START + i * BIT(pageBitsForSize(IA32_4K))) & MASK(pageBitsForSize(IA32_4M))) >> pageBitsForSize(IA32_4K));
|
||||
pt[idx] = pte;
|
||||
idx++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_IOMMU
|
||||
/* map kernel devices: IOMMUs */
|
||||
|
|
|
|||
|
|
@ -91,6 +91,8 @@ Arch_initFpu(void)
|
|||
/* Enable FPU / SSE / SSE2 / SSE3 / SSSE3 / SSE4 Extensions. */
|
||||
write_cr4(read_cr4() | CR4_OSFXSR);
|
||||
|
||||
/* Enable the FPU in general. */
|
||||
write_cr0((read_cr0() & ~CR0_EMULATION) | CR0_MONITOR_COPROC | CR0_NUMERIC_ERROR);
|
||||
/* Enable the FPU in general. Although leave it in a state where it will
|
||||
* generate a fault if someone tries to use it as we implement lazy
|
||||
* switching */
|
||||
write_cr0((read_cr0() & ~CR0_EMULATION) | CR0_MONITOR_COPROC | CR0_NUMERIC_ERROR | CR0_TASK_SWITCH);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,9 +9,6 @@
|
|||
*/
|
||||
|
||||
#include <machine/assembler.h>
|
||||
#include <arch/api/syscall.h>
|
||||
|
||||
# minimum and maximum seL4 syscall number
|
||||
|
||||
# On kernel entry, ESP points to the end of the thread's registers array.
|
||||
# Hardware pushes onto the stack SS, ESP, EFLAGS, CS, NextEIP and Error,
|
||||
|
|
@ -349,70 +346,14 @@ handle_interrupt:
|
|||
andb %bl, %dl # we have a kernel exception if both BL and DL are 1
|
||||
jnz kernel_exception
|
||||
|
||||
# save ESP (which now points to the current TCB)
|
||||
movl %esp, %edx
|
||||
|
||||
# save ECX (which contains the interrupt vector)
|
||||
movl %ecx, ia32KScurInterrupt
|
||||
|
||||
# switch to kernel stack
|
||||
leal _kernel_stack_top, %esp
|
||||
|
||||
# the code below assumes:
|
||||
# - EAX contains the syscall number
|
||||
# - ECX contains the interrupt vector
|
||||
# - EDX contains the current TCB
|
||||
# Place the syscall number in the second argument slot
|
||||
movl %eax, %edx
|
||||
|
||||
# depending on the interrupt vector, call appropriate handling function
|
||||
cmpl $0x07, %ecx # 0x07 = int_unimpl_dev
|
||||
je handle_unimplemented_device
|
||||
cmpl $0x0e, %ecx # 0x0e = int_page_fault
|
||||
je handle_page_fault
|
||||
cmpl $0x20, %ecx # 0x20 = int_irq_isa_min
|
||||
jb handle_fault
|
||||
cmpl $0x50, %ecx # 0x50 = int_trap_min
|
||||
jb handle_IRQ
|
||||
cmpl $0xff, %ecx # 0xff = int_spurious
|
||||
je restore_user_context # ignore and do not ack spurious interrupt
|
||||
|
||||
# Here we know we have a trap. It is interpreted as unknown syscall.
|
||||
# We have to adjust the FaultEIP to point to the trapping INT instruction
|
||||
# by subtracting 2. EDX contains the current TCB.
|
||||
subl $2, 0x2c(%edx)
|
||||
|
||||
# The trap number is stored in the MSB and the 24-bit syscall number
|
||||
# in the LSBs of EAX.
|
||||
shll $24, %ecx
|
||||
andl $0x00ffffff, %eax
|
||||
orl %ecx, %eax
|
||||
|
||||
jmp undefined_syscall
|
||||
|
||||
handle_fault:
|
||||
# fault code corresponds to error code of the exception
|
||||
pushl 0x34(%edx) # push Error
|
||||
# fault number corresponds to exception vector number
|
||||
pushl %ecx
|
||||
call handleUserLevelFault
|
||||
addl $8, %esp
|
||||
jmp restore_user_context
|
||||
|
||||
handle_page_fault:
|
||||
movl 0x34(%edx), %edx # get Error code from TCB
|
||||
shrl $4, %edx # get I/D flag
|
||||
andl $1, %edx # mask rest of error code
|
||||
pushl %edx # vm_fault_type_t (0 = data, 1 = instruction)
|
||||
call handleVMFaultEvent
|
||||
addl $4, %esp
|
||||
jmp restore_user_context
|
||||
|
||||
handle_unimplemented_device:
|
||||
call handleUnimplementedDevice
|
||||
jmp restore_user_context
|
||||
|
||||
handle_IRQ:
|
||||
call handleInterruptEntry
|
||||
jmp restore_user_context
|
||||
# gtfo to C land, we will not return
|
||||
call c_handle_interrupt
|
||||
|
||||
# Handle a kernel exception
|
||||
|
||||
|
|
@ -444,27 +385,6 @@ BEGIN_FUNC(kernel_exception)
|
|||
jmp halt
|
||||
END_FUNC(kernel_exception)
|
||||
|
||||
#ifdef FASTPATH
|
||||
|
||||
# Calls the slowpath from the fastpath
|
||||
# Defined with fastcall calling convention
|
||||
BEGIN_FUNC(slowpath)
|
||||
# indicate int_invalid as the interrupt currently being served
|
||||
movl $-1, ia32KScurInterrupt
|
||||
|
||||
# syscall is in ECX
|
||||
pushl %ecx
|
||||
|
||||
# Update NextEIP
|
||||
movl ksCurThread, %ecx
|
||||
addl $2, 56(%ecx)
|
||||
|
||||
call handleSyscall
|
||||
jmp restore_user_context
|
||||
END_FUNC(slowpath)
|
||||
|
||||
#endif
|
||||
|
||||
#define SET_SEL(sel, offset, val) \
|
||||
cmpl $val, (offset)(%esp); \
|
||||
je 1f; \
|
||||
|
|
@ -507,131 +427,15 @@ BEGIN_FUNC(handle_syscall)
|
|||
SET_SEL(ds, 7 * 4, 0x23)
|
||||
SET_SEL(es, 8 * 4, 0x23)
|
||||
|
||||
# Perform this comparison as soon as we stop doing operations that clobber the FLAGS
|
||||
#ifdef FASTPATH
|
||||
cmpl $SYSCALL_REPLY_WAIT, %eax
|
||||
#endif
|
||||
|
||||
# switch to kernel stack
|
||||
leal _kernel_stack_top, %esp
|
||||
|
||||
#ifdef FASTPATH
|
||||
# Shuffle some register to suit the fastcall calling convention
|
||||
movl %ebx, %ecx
|
||||
movl %esi, %edx
|
||||
je fastpath_reply_wait
|
||||
cmpl $SYSCALL_CALL, %eax
|
||||
je fastpath_call
|
||||
#endif
|
||||
# Push all the arguments for c_handle_syscall
|
||||
pushl %esi # msgInfo
|
||||
pushl %ebx # cptr
|
||||
pushl %eax # syscall number
|
||||
|
||||
# indicate int_invalid as the interrupt currently being served
|
||||
movl $-1, ia32KScurInterrupt
|
||||
# gtfo to C land, we will not return
|
||||
call c_handle_syscall
|
||||
|
||||
# increment NextEIP
|
||||
movl ksCurThread, %ecx
|
||||
addl $2, 56(%ecx)
|
||||
|
||||
# check that syscall number is in range
|
||||
cmpl $SYSCALL_MAX, %eax
|
||||
jg undefined_syscall
|
||||
cmpl $SYSCALL_MIN, %eax
|
||||
jl undefined_syscall
|
||||
|
||||
# we have a seL4 syscall
|
||||
pushl %eax
|
||||
call handleSyscall
|
||||
jmp restore_user_context
|
||||
|
||||
undefined_syscall:
|
||||
pushl %eax
|
||||
call handleUnknownSyscall
|
||||
# fall through to restore_user_context
|
||||
END_FUNC(handle_syscall)
|
||||
|
||||
#define POP_SEL(sel, val) \
|
||||
cmpl $val, (%esp); \
|
||||
je 1f; \
|
||||
popl %sel; \
|
||||
jmp 2f; \
|
||||
1: \
|
||||
addl $4, %esp; \
|
||||
2:
|
||||
|
||||
BEGIN_FUNC(restore_user_context)
|
||||
# save kernel ESP to TSS for next kernel entry
|
||||
movl ksCurThread, %esp # point ESP to current user_context_t
|
||||
addl $0x4c, %esp # size of registers array (0x4c bytes)
|
||||
leal ia32KStss, %ecx
|
||||
movl %esp, 4(%ecx) # tss.esp0 = pointer to end of thread's registers array
|
||||
subl $0x4c, %esp # restore ESP to point to current TCB
|
||||
|
||||
# disable the FPU, unless owned by the current thread
|
||||
cmpl %esp, ia32KSfpuOwner
|
||||
je fpu_enable
|
||||
movl %cr0, %eax
|
||||
orl $0x8, %eax
|
||||
movl %eax, %cr0
|
||||
|
||||
fpu_done:
|
||||
# determine whether we entered via interrupt or syscall
|
||||
cmpl $-1, 0x34(%esp) # if (Error == -1)
|
||||
je restore_syscall
|
||||
|
||||
# we entered via interrupt, i.e. we return via iret
|
||||
# precondition: ESP == ksCurThread
|
||||
popl %eax
|
||||
popl %ebx
|
||||
popl %ecx
|
||||
popl %edx
|
||||
popl %esi
|
||||
popl %edi
|
||||
popl %ebp
|
||||
popl %ds
|
||||
popl %es
|
||||
popl %fs
|
||||
popl %gs
|
||||
addl $4, %esp # skip FaultEIP
|
||||
addl $4, %esp # skip TLS_BASE
|
||||
addl $4, %esp # skip the error code
|
||||
iret
|
||||
|
||||
fpu_enable:
|
||||
clts
|
||||
jmp fpu_done
|
||||
|
||||
restore_syscall:
|
||||
# we entered via sysenter, i.e. we return via sysexit
|
||||
# precondition: ESP == ksCurThread
|
||||
popl %eax # restore EAX (syscall number)
|
||||
popl %ebx # restore EBX (cap/badge register)
|
||||
addl $8, %esp # skip ECX and EDX (will contain ESP and NextEIP)
|
||||
popl %esi # restore ESI (msgInfo register)
|
||||
popl %edi # restore EDI (message register)
|
||||
popl %ebp # restore EBP (message register)
|
||||
# Only pop the code and data selectors if their values have changed from the default
|
||||
POP_SEL(ds, 0x23)
|
||||
POP_SEL(es, 0x23)
|
||||
# Have to reload fs and gs for update to the selectors to become visible
|
||||
popl %fs
|
||||
popl %gs
|
||||
addl $4, %esp # skip FaultEIP
|
||||
addl $4, %esp # skip TLS_BASE
|
||||
addl $4, %esp # skip Error
|
||||
|
||||
popl %edx # restore NextEIP (passed in EDX)
|
||||
addl $4, %esp # skip CS
|
||||
andl $~0x200, (%esp) # clear interrupt bit before popping into EFLAGS
|
||||
popfl # restore EFLAGS with interrupts off
|
||||
orl $0x200, -4(%esp) # set interrupt bit again
|
||||
popl %ecx # restore ESP (passed in ECX)
|
||||
# skip SS
|
||||
|
||||
# We have following register contents when returning:
|
||||
# EAX : syscall number (needed to restart syscall)
|
||||
# ECX : user ESP
|
||||
# EDX : user NextEIP
|
||||
|
||||
sti # now enable the interrupts, which were disabled
|
||||
# by sysenter (will be enabled AFTER sysexit)
|
||||
sysexit # return to user space
|
||||
END_FUNC(restore_user_context)
|
||||
|
|
|
|||
|
|
@ -90,8 +90,8 @@ invokeIRQControl(irq_t irq, cte_t *handlerSlot, cte_t *controlSlot)
|
|||
}
|
||||
|
||||
exception_t
|
||||
decodeIRQHandlerInvocation(word_t label, irq_t irq,
|
||||
extra_caps_t extraCaps)
|
||||
decodeIRQHandlerInvocation(word_t label, unsigned int length, irq_t irq,
|
||||
extra_caps_t extraCaps, word_t *buffer)
|
||||
{
|
||||
switch (label) {
|
||||
case IRQAckIRQ:
|
||||
|
|
@ -131,6 +131,21 @@ decodeIRQHandlerInvocation(word_t label, irq_t irq,
|
|||
setThreadState(ksCurThread, ThreadState_Restart);
|
||||
invokeIRQHandler_ClearIRQHandler(irq);
|
||||
return EXCEPTION_NONE;
|
||||
case IRQSetMode: {
|
||||
bool_t trig, pol;
|
||||
|
||||
if (length < 2) {
|
||||
userError("IRQSetMode: Not enough arguments", length);
|
||||
current_syscall_error.type = seL4_TruncatedMessage;
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
trig = getSyscallArg(0, buffer);
|
||||
pol = getSyscallArg(1, buffer);
|
||||
|
||||
setThreadState(ksCurThread, ThreadState_Restart);
|
||||
invokeIRQHandler_SetMode(irq, !!trig, !!pol);
|
||||
return EXCEPTION_NONE;
|
||||
}
|
||||
|
||||
default:
|
||||
userError("IRQHandler: Illegal operation.");
|
||||
|
|
@ -145,6 +160,11 @@ invokeIRQHandler_AckIRQ(irq_t irq)
|
|||
maskInterrupt(false, irq);
|
||||
}
|
||||
|
||||
void invokeIRQHandler_SetMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow)
|
||||
{
|
||||
setInterruptMode(irq, levelTrigger, polarityLow);
|
||||
}
|
||||
|
||||
void
|
||||
invokeIRQHandler_SetIRQHandler(irq_t irq, cap_t cap, cte_t *slot)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -668,8 +668,8 @@ decodeInvocation(word_t label, unsigned int length,
|
|||
extraCaps, buffer);
|
||||
|
||||
case cap_irq_handler_cap:
|
||||
return decodeIRQHandlerInvocation(label,
|
||||
cap_irq_handler_cap_get_capIRQ(cap), extraCaps);
|
||||
return decodeIRQHandlerInvocation(label, length,
|
||||
cap_irq_handler_cap_get_capIRQ(cap), extraCaps, buffer);
|
||||
|
||||
default:
|
||||
fail("Invalid cap type");
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
/* Available physical memory regions on platform (RAM) */
|
||||
/* NOTE: Regions are not allowed to be adjacent! */
|
||||
/* and must be page-aligned */
|
||||
const p_region_t BOOT_RODATA avail_p_regs[] = {
|
||||
/* 2 GiB -1 page to prevent uin32_t overflow */
|
||||
{ /* .start = */ 0x80000000, /* .end = */ 0xfffff000 }
|
||||
|
|
@ -38,7 +39,10 @@ get_avail_p_reg(unsigned int i)
|
|||
{
|
||||
return avail_p_regs[i];
|
||||
}
|
||||
|
||||
/*
|
||||
* We're limited to one page of boot data.
|
||||
* Exclude some devices.
|
||||
*/
|
||||
const p_region_t BOOT_RODATA dev_p_regs[] = {
|
||||
{ /* .start */ RPM_PADDR , /* .end */ RPM_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ RPM_TIMERS_PADDR , /* .end */ RPM_TIMERS_PADDR + (1 << PAGE_BITS) },
|
||||
|
|
@ -145,27 +149,49 @@ const p_region_t BOOT_RODATA dev_p_regs[] = {
|
|||
{ /* .start */ SIC_APU_PADDR , /* .end */ SIC_APU_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ SIC_NON_SECURE_PADDR , /* .end */ SIC_NON_SECURE_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ INTCTL0_PADDR , /* .end */ INTCTL0_PADDR + (1 << PAGE_BITS) },
|
||||
#if (INTCTL1_PADDR & 0xfff) == 0
|
||||
{ /* .start */ INTCTL1_PADDR , /* .end */ INTCTL1_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
#if (INTCTL2_PADDR & 0xfff) == 0
|
||||
{ /* .start */ INTCTL2_PADDR , /* .end */ INTCTL2_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
#if (INTCTL3_PADDR & 0xfff) == 0
|
||||
{ /* .start */ INTCTL3_PADDR , /* .end */ INTCTL3_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
#if (INTCTL4_PADDR & 0xfff) == 0
|
||||
{ /* .start */ INTCTL4_PADDR , /* .end */ INTCTL4_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
#if (INTCTL5_PADDR & 0xfff) == 0
|
||||
{ /* .start */ INTCTL5_PADDR , /* .end */ INTCTL5_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
#if (INTCTL6_PADDR & 0xfff) == 0
|
||||
{ /* .start */ INTCTL6_PADDR , /* .end */ INTCTL6_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
#if (INTCTL7_PADDR & 0xfff) == 0
|
||||
{ /* .start */ INTCTL7_PADDR , /* .end */ INTCTL7_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
{ /* .start */ SDC2_PADDR , /* .end */ SDC2_PADDR + (1 << PAGE_BITS) },
|
||||
#if (SDC2_DML_PADDR & 0xfff) == 0
|
||||
{ /* .start */ SDC2_DML_PADDR , /* .end */ SDC2_DML_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
{ /* .start */ SDC2_BAM_PADDR , /* .end */ SDC2_BAM_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ SDC3_PADDR , /* .end */ SDC3_PADDR + (1 << PAGE_BITS) },
|
||||
#if (SDC3_DML_PADDR & 0xfff) == 0
|
||||
{ /* .start */ SDC3_DML_PADDR , /* .end */ SDC3_DML_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
{ /* .start */ SDC3_BAM_PADDR , /* .end */ SDC3_BAM_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ SDC4_PADDR , /* .end */ SDC4_PADDR + (1 << PAGE_BITS) },
|
||||
#if (SDC4_DML_PADDR & 0xfff) == 0
|
||||
{ /* .start */ SDC4_DML_PADDR , /* .end */ SDC4_DML_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
{ /* .start */ SDC4_BAM_PADDR , /* .end */ SDC4_BAM_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ BAM_DMA_PADDR , /* .end */ BAM_DMA_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ BAM_DMA_BAM_PADDR , /* .end */ BAM_DMA_BAM_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ BAM_DMA_BAM_XPU_PADDR , /* .end */ BAM_DMA_BAM_XPU_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ SDC1_PADDR , /* .end */ SDC1_PADDR + (1 << PAGE_BITS) },
|
||||
#if (SDC1_DML_PADDR & 0xfff) == 0
|
||||
{ /* .start */ SDC1_DML_PADDR , /* .end */ SDC1_DML_PADDR + (1 << PAGE_BITS) },
|
||||
#endif
|
||||
{ /* .start */ SDC1_BAM_PADDR , /* .end */ SDC1_BAM_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ SPS_GSBI1_PADDR , /* .end */ SPS_GSBI1_PADDR + (1 << PAGE_BITS) },
|
||||
{ /* .start */ SPS_UART1_DM_PADDR , /* .end */ SPS_UART1_DM_PADDR + (1 << PAGE_BITS) },
|
||||
|
|
|
|||
|
|
@ -22,3 +22,30 @@ config IOMMU
|
|||
default y
|
||||
help
|
||||
IOMMU support for VT-d enabled chipset
|
||||
|
||||
choice
|
||||
prompt "IRQ Controller"
|
||||
depends on ARCH_IA32
|
||||
default IRQ_PIC
|
||||
help
|
||||
Select the IRQ controller seL4 will use. Code for others may
|
||||
still be included if needed to disable at run time
|
||||
config IRQ_PIC
|
||||
bool "PIC"
|
||||
help
|
||||
Use the legacy PIC controller
|
||||
config IRQ_IOAPIC
|
||||
bool "IOAPIC"
|
||||
help
|
||||
Use one or more IOAPIC controllers
|
||||
endchoice
|
||||
|
||||
config MAX_NUM_IOAPIC
|
||||
prompt "Max supported IOAPICs"
|
||||
depends on ARCH_IA32
|
||||
int
|
||||
default 1
|
||||
help
|
||||
Configure the maximum number of IOAPIC controllers that can
|
||||
be supported. SeL4 will detect IOAPICs regardless of whether
|
||||
the IOAPIC will actually be used as the final IRQ controller
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ PLAT_C_SOURCES += machine/acpi.c \
|
|||
machine/hardware.c \
|
||||
machine/pci.c \
|
||||
machine/pic.c \
|
||||
machine/ioapic.c \
|
||||
machine/pit.c \
|
||||
machine/io.c
|
||||
ifdef DEBUG
|
||||
|
|
|
|||
|
|
@ -256,7 +256,9 @@ BOOT_CODE uint32_t
|
|||
acpi_madt_scan(
|
||||
acpi_rsdt_t* acpi_rsdt,
|
||||
cpu_id_t* cpu_list,
|
||||
uint32_t max_list_len
|
||||
uint32_t max_list_len,
|
||||
uint32_t* num_ioapic,
|
||||
paddr_t* ioapic_paddrs
|
||||
)
|
||||
{
|
||||
unsigned int entries;
|
||||
|
|
@ -270,6 +272,7 @@ acpi_madt_scan(
|
|||
acpi_rsdt_mapped = (acpi_rsdt_t*)acpi_table_init(acpi_rsdt, ACPI_RSDT);
|
||||
|
||||
num_cpu = 0;
|
||||
*num_ioapic = 0;
|
||||
|
||||
assert(acpi_rsdt_mapped->header.length >= sizeof(acpi_header_t));
|
||||
entries = (acpi_rsdt_mapped->header.length - sizeof(acpi_header_t)) / sizeof(acpi_header_t*);
|
||||
|
|
@ -307,6 +310,19 @@ acpi_madt_scan(
|
|||
((acpi_madt_ioapic_t*)acpi_madt_header)->ioapic_addr,
|
||||
((acpi_madt_ioapic_t*)acpi_madt_header)->gsib
|
||||
);
|
||||
if (*num_ioapic == CONFIG_MAX_NUM_IOAPIC) {
|
||||
printf("ACPI: Not recording this IOAPIC, only support %d\n", CONFIG_MAX_NUM_IOAPIC);
|
||||
} else {
|
||||
ioapic_paddrs[*num_ioapic] = ((acpi_madt_ioapic_t*)acpi_madt_header)->ioapic_addr;
|
||||
(*num_ioapic)++;
|
||||
}
|
||||
break;
|
||||
case MADT_ISO:
|
||||
printf("ACIP: MADT_ISO bus=%d source=%d gsi=%d flags=0x%x\n",
|
||||
((acpi_madt_iso_t*)acpi_madt_header)->bus,
|
||||
((acpi_madt_iso_t*)acpi_madt_header)->source,
|
||||
((acpi_madt_iso_t*)acpi_madt_header)->gsi,
|
||||
((acpi_madt_iso_t*)acpi_madt_header)->flags);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include <arch/model/statedata.h>
|
||||
#include <arch/linker.h>
|
||||
#include <plat/machine/pic.h>
|
||||
#include <plat/machine/ioapic.h>
|
||||
#include <plat/machine.h>
|
||||
|
||||
#ifdef CONFIG_IOMMU
|
||||
|
|
@ -43,16 +44,35 @@ void platAddDevices(void)
|
|||
/* Enable or disable irq according to the 'mask' flag. */
|
||||
void maskInterrupt(bool_t mask, irq_t irq)
|
||||
{
|
||||
assert(irq >= irq_isa_min);
|
||||
assert(irq >= irq_controller_min);
|
||||
assert(irq <= maxIRQ);
|
||||
|
||||
if (irq <= irq_isa_max) {
|
||||
if (irq <= irq_controller_max) {
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
ioapic_mask_irq(mask, irq);
|
||||
#else
|
||||
pic_mask_irq(mask, irq);
|
||||
#endif
|
||||
} else {
|
||||
/* we can't mask/unmask specific APIC vectors (e.g. MSIs/IPIs) */
|
||||
}
|
||||
}
|
||||
|
||||
/* Set mode of an irq */
|
||||
void setInterruptMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow)
|
||||
{
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
assert(irq >= irq_ioapic_min);
|
||||
assert(irq <= maxIRQ);
|
||||
|
||||
if (irq <= irq_ioapic_max) {
|
||||
ioapic_set_mode(irq, levelTrigger, polarityLow);
|
||||
} else {
|
||||
/* No mode setting for specific APIC vectors */
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Handle a platform-reserved IRQ. */
|
||||
void handleReservedIRQ(irq_t irq)
|
||||
{
|
||||
|
|
@ -78,14 +98,25 @@ irq_t getActiveIRQ(void)
|
|||
/* Checks for pending IRQ */
|
||||
bool_t isIRQPending(void)
|
||||
{
|
||||
return apic_is_interrupt_pending() || pic_is_irq_pending();
|
||||
if (apic_is_interrupt_pending()) {
|
||||
return true;
|
||||
}
|
||||
#ifdef CONFIG_IRQ_PIC
|
||||
if (pic_is_irq_pending()) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void ackInterrupt(irq_t irq)
|
||||
{
|
||||
#ifdef CONFIG_IRQ_PIC
|
||||
if (irq <= irq_isa_max) {
|
||||
pic_ack_active_irq();
|
||||
} else {
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
apic_ack_active_interrupt();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
177
src/plat/pc99/machine/ioapic.c
Normal file
177
src/plat/pc99/machine/ioapic.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright 2014, General Dynamics C4 Systems
|
||||
*
|
||||
* This software may be distributed and modified according to the terms of
|
||||
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
|
||||
* See "LICENSE_GPLv2.txt" for details.
|
||||
*
|
||||
* @TAG(GD_GPL)
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#ifdef CONFIG_IRQ_IOAPIC
|
||||
|
||||
#include <arch/linker.h>
|
||||
#include <plat/machine/io.h>
|
||||
#include <plat/machine/hardware.h>
|
||||
#include <plat/machine/ioapic.h>
|
||||
|
||||
#define IOAPIC_REGSEL 0x00
|
||||
#define IOAPIC_WINDOW 0x10
|
||||
|
||||
#define IOAPIC_REG_IOAPICID 0x00
|
||||
#define IOAPIC_REG_IOREDTBL 0x10
|
||||
|
||||
#define IOREDTBL_LOW(reg) (IOAPIC_REG_IOREDTBL + (reg) * 2)
|
||||
#define IOREDTBL_HIGH(reg) (IOREDTBL_LOW(reg) + 1)
|
||||
|
||||
#define IOREDTBL_LOW_INTERRUPT_MASK BIT(16)
|
||||
#define IOREDTBL_LOW_TRIGGER_MODE_LEVEL BIT(15)
|
||||
#define IOREDTBL_LOW_POLARITY_LOW BIT(13)
|
||||
#define IOREDTBL_LOW_DEST_MODE_LOGCIAL BIT(11)
|
||||
|
||||
#define IOAPICID_ID_BITS 4
|
||||
#define IOAPICID_ID_OFFSET 24
|
||||
|
||||
#define IOREDTBL_HIGH_RESERVED_BITS 24
|
||||
|
||||
/* Cache what we believe is in the low word of the IOREDTBL. This
|
||||
* has all the state of trigger modes etc etc */
|
||||
static uint32_t ioredtbl_state[IOAPIC_IRQ_LINES * CONFIG_MAX_NUM_IOAPIC];
|
||||
|
||||
/* Number of IOAPICs in the system */
|
||||
static uint32_t num_ioapics = 0;
|
||||
|
||||
/* In debug mode we track whether an unmasked vector has
|
||||
* had its mode set. This is to catch bad user level code */
|
||||
#ifdef DEBUG
|
||||
static bool_t done_set_mode[IOAPIC_IRQ_LINES * CONFIG_MAX_NUM_IOAPIC] = { 0 };
|
||||
#endif
|
||||
|
||||
static void ioapic_write(uint32_t ioapic, uint32_t reg, uint32_t value)
|
||||
{
|
||||
*(volatile uint32_t*)((uint32_t)(PPTR_IOAPIC_START + ioapic * BIT(PAGE_BITS)) + reg) = value;
|
||||
}
|
||||
|
||||
static uint32_t ioapic_read(uint32_t ioapic, uint32_t reg)
|
||||
{
|
||||
return *(volatile uint32_t*)((uint32_t)(PPTR_IOAPIC_START + ioapic * BIT(PAGE_BITS)) + reg);
|
||||
}
|
||||
|
||||
static bool_t in_list(uint32_t size, cpu_id_t *list, cpu_id_t target)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i = 0; i < size; i++) {
|
||||
if (list[i] == target) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void single_ioapic_init(uint32_t ioapic, cpu_id_t ioapic_id, cpu_id_t delivery_cpu)
|
||||
{
|
||||
uint32_t id_reg;
|
||||
uint32_t i;
|
||||
/* Write the ID to the ioapic */
|
||||
ioapic_write(ioapic, IOAPIC_REGSEL, IOAPIC_REG_IOAPICID);
|
||||
id_reg = ioapic_read(ioapic, IOAPIC_WINDOW);
|
||||
/* perform mask to preserve the reserved bits */
|
||||
id_reg &= ~(MASK(IOAPICID_ID_BITS) << IOAPICID_ID_OFFSET);
|
||||
id_reg |= ioapic_id << IOAPICID_ID_OFFSET;
|
||||
/* Mask all the IRQs and set default delivery details.
|
||||
* attempt to deliberately set a trigger mode and level
|
||||
* setting that is LEAST likely to be correct. This is
|
||||
* to ensure user code sets it correctly and cannot get
|
||||
* away with it happening to be correct */
|
||||
for (i = 0; i < IOAPIC_IRQ_LINES; i++) {
|
||||
/* Send to desired cpu */
|
||||
ioapic_write(ioapic, IOAPIC_REGSEL, IOREDTBL_HIGH(i));
|
||||
ioapic_write(ioapic, IOAPIC_WINDOW, (ioapic_read(ioapic, IOAPIC_WINDOW) & MASK(IOREDTBL_HIGH_RESERVED_BITS)) | (delivery_cpu << IOREDTBL_HIGH_RESERVED_BITS));
|
||||
/* Mask and set to level trigger high polarity and make the delivery vector */
|
||||
ioredtbl_state[i] = IOREDTBL_LOW_INTERRUPT_MASK |
|
||||
IOREDTBL_LOW_TRIGGER_MODE_LEVEL |
|
||||
(i + IRQ_INT_OFFSET);
|
||||
ioapic_write(ioapic, IOAPIC_REGSEL, IOREDTBL_LOW(i));
|
||||
/* The upper 16 bits are reserved, so we make sure to preserve them */
|
||||
ioredtbl_state[i] |= ioapic_read(ioapic, IOAPIC_WINDOW) & ~MASK(16);
|
||||
ioapic_write(ioapic, IOAPIC_WINDOW, ioredtbl_state[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* To guarantee we will be able to find enough free apic ids there needs to be less than
|
||||
* 2^4 cpus + ioapics in the system */
|
||||
compile_assert(ioapic_id_will_not_overflow, CONFIG_MAX_NUM_NODES + CONFIG_MAX_NUM_IOAPIC < 16);
|
||||
|
||||
void ioapic_init(uint32_t num_nodes, cpu_id_t *cpu_list, uint32_t num_ioapic)
|
||||
{
|
||||
uint32_t ioapic;
|
||||
cpu_id_t ioapic_id = 0;
|
||||
num_ioapics = num_ioapic;
|
||||
for (ioapic = 0; ioapic < num_ioapic; ioapic++) {
|
||||
/* Determine the next free apic ID */
|
||||
while (in_list(num_nodes, cpu_list, ioapic_id)) {
|
||||
ioapic_id++;
|
||||
}
|
||||
/* ioapic id field is 4 bits. this assert passing should be
|
||||
* guaranteed by the compile assert above this function, hence
|
||||
* this does not need to be a run time check */
|
||||
assert(ioapic_id < BIT(4));
|
||||
/* Init this ioapic */
|
||||
single_ioapic_init(ioapic, ioapic_id, cpu_list[0]);
|
||||
/* Increment the id */
|
||||
ioapic_id++;
|
||||
}
|
||||
}
|
||||
|
||||
void ioapic_mask_irq(bool_t mask, irq_t irq)
|
||||
{
|
||||
uint32_t ioapic = irq / IOAPIC_IRQ_LINES;
|
||||
uint32_t index = irq % IOAPIC_IRQ_LINES;
|
||||
if (ioapic >= num_ioapics) {
|
||||
/* silently ignore requests to non existent parts of the interrupt space */
|
||||
return;
|
||||
}
|
||||
if (mask) {
|
||||
ioredtbl_state[irq] |= IOREDTBL_LOW_INTERRUPT_MASK;
|
||||
} else {
|
||||
ioredtbl_state[irq] &= ~IOREDTBL_LOW_INTERRUPT_MASK;
|
||||
#ifdef DEBUG
|
||||
if (!done_set_mode[irq]) {
|
||||
printf("Unmasking IOAPIC source %d on ioapic %d without ever setting its mode!\n", index, ioapic);
|
||||
/* Set the flag so we don't repeatedly warn */
|
||||
done_set_mode[irq] = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
ioapic_write(ioapic, IOAPIC_REGSEL, IOREDTBL_LOW(index));
|
||||
ioapic_write(ioapic, IOAPIC_WINDOW, ioredtbl_state[irq]);
|
||||
}
|
||||
|
||||
void ioapic_set_mode(irq_t irq, bool_t levelTrigger, bool_t polarityLow)
|
||||
{
|
||||
uint32_t ioapic = irq / IOAPIC_IRQ_LINES;
|
||||
uint32_t index = irq % IOAPIC_IRQ_LINES;
|
||||
if (ioapic >= num_ioapics) {
|
||||
/* silently ignore requests to non existent parts of the interrupt space */
|
||||
return;
|
||||
}
|
||||
if (levelTrigger) {
|
||||
ioredtbl_state[irq] |= IOREDTBL_LOW_TRIGGER_MODE_LEVEL;
|
||||
} else {
|
||||
ioredtbl_state[irq] &= ~IOREDTBL_LOW_TRIGGER_MODE_LEVEL;
|
||||
}
|
||||
if (polarityLow) {
|
||||
ioredtbl_state[irq] |= IOREDTBL_LOW_POLARITY_LOW;
|
||||
} else {
|
||||
ioredtbl_state[irq] &= ~IOREDTBL_LOW_POLARITY_LOW;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
done_set_mode[irq] = 1;
|
||||
#endif
|
||||
ioapic_write(ioapic, IOAPIC_REGSEL, IOREDTBL_LOW(index));
|
||||
ioapic_write(ioapic, IOAPIC_WINDOW, ioredtbl_state[irq]);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_IOAPIC */
|
||||
|
|
@ -33,6 +33,16 @@ pic_remap_irqs(interrupt_t interrupt)
|
|||
out8(PIC2_BASE + 1, 0x0);
|
||||
}
|
||||
|
||||
BOOT_CODE void pic_disable(void)
|
||||
{
|
||||
/* We assume that pic_remap_irqs has already been called and
|
||||
* just mask all the irqs */
|
||||
out8(PIC1_BASE + 1, 0xff);
|
||||
out8(PIC2_BASE + 1, 0xff);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IRQ_PIC
|
||||
|
||||
void pic_mask_irq(bool_t mask, irq_t irq)
|
||||
{
|
||||
uint8_t bit_mask;
|
||||
|
|
@ -84,3 +94,5 @@ void pic_ack_active_irq(void)
|
|||
/* ack master PIC */
|
||||
out8(PIC1_BASE, 0x20);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2014, NICTA
|
||||
#
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# Copyright 2014, NICTA
|
||||
#
|
||||
|
|
@ -41,13 +41,14 @@ kernel_header_template = \
|
|||
#define SYSCALL_{{upper(syscall)}} ({{syscall_number}})
|
||||
{{py:syscall_number -= 1}}
|
||||
{{endfor}}
|
||||
{{py:syscall_max = -len(list)}}
|
||||
{{endfor}}
|
||||
|
||||
#endif
|
||||
|
||||
#define SYSCALL_MAX (-1)
|
||||
#define SYSCALL_MIN ({{syscall_number + 1}})
|
||||
|
||||
#else /* C definitions */
|
||||
#ifndef __ASSEMBLER__
|
||||
|
||||
enum syscall {
|
||||
{{py:syscall_number = -1}}
|
||||
|
|
@ -66,7 +67,7 @@ enum syscall {
|
|||
};
|
||||
typedef uint32_t syscall_t;
|
||||
|
||||
#endif /* ASSEMBLER */
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_API_SYSCALL_H */
|
||||
"""
|
||||
|
|
|
|||
Loading…
Reference in a new issue