Merge pull request #60 from simonduq/pr/rm-galileo
Removed platform Galileo
This commit is contained in:
commit
833ad6fb33
|
@ -1,48 +0,0 @@
|
|||
CONTIKI_CPU_DIRS += . init/common
|
||||
|
||||
CONTIKI_SOURCEFILES += gdt.c helpers.S idt.c cpu.c
|
||||
|
||||
CC = gcc
|
||||
LD = $(CC)
|
||||
# Use gcc to invoke the assembler so that the preprocessor will be run on each
|
||||
# file first, enabling us to use macros within assembly language files:
|
||||
AS = $(CC)
|
||||
OBJCOPY = objcopy
|
||||
SIZE = size
|
||||
STRIP = strip
|
||||
|
||||
# Omit exception handling unwind tables (see
|
||||
# http://wiki.dwarfstd.org/index.php?title=Exception_Handling). Removing these
|
||||
# tables saves space and has not caused any readily-apparent functional
|
||||
# changes.
|
||||
#
|
||||
# Furthermore, the .eh_frame and .eh_frame_hdr sections that are otherwise
|
||||
# generated are treated as code sections by the UEFI GenFw program, since they
|
||||
# are read-only alloc sections. They get grouped with the actual code
|
||||
# sections, ahead of the data sections. This perturbs symbols and complicates
|
||||
# debugging.
|
||||
#
|
||||
# Synchronize the unwind table options here with the CFLAGS and CXXFLAGS in
|
||||
# ./bsp/libc/build_newlib.sh.
|
||||
CFLAGS += -Wall -fno-asynchronous-unwind-tables -fno-unwind-tables
|
||||
LDFLAGS += -Wl,-Map=contiki-$(TARGET).map,--build-id=none
|
||||
|
||||
ifeq ($(WERROR),1)
|
||||
CFLAGS += -Werror
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_RELEASE),1)
|
||||
CFLAGS += -Os -fno-strict-aliasing -ffunction-sections -fdata-sections
|
||||
# XXX: --gc-sections can be very tricky sometimes. If somehow the release
|
||||
# binary seems to be broken, check if removing this option fixes the issue.
|
||||
# Applying the --strip-all option to the UEFI build may induce an "Invalid operation" error.
|
||||
# The UEFI GenFw program strips symbols.
|
||||
MULTIBOOT_LDFLAGS += -Wl,--strip-all,--gc-sections
|
||||
else
|
||||
CFLAGS += -O0
|
||||
ifeq ($(findstring clang,$(CC)),clang)
|
||||
CFLAGS += -g
|
||||
else
|
||||
CFLAGS += -ggdb3
|
||||
endif
|
||||
endif
|
|
@ -1,93 +0,0 @@
|
|||
# See mm/README.md for a description of available settings:
|
||||
X86_CONF_PROT_DOMAINS ?= none
|
||||
|
||||
include $(CONTIKI)/arch/cpu/x86/Makefile.x86_common
|
||||
|
||||
CONTIKI_CPU_DIRS += drivers/legacy_pc drivers/quarkX1000 init/legacy_pc net mm
|
||||
|
||||
CONTIKI_SOURCEFILES += bootstrap_quarkX1000.S rtc.c pit.c pic.c irq.c nmi.c pci.c uart-16x50.c uart.c gpio.c i2c.c eth.c shared-isr.c
|
||||
CONTIKI_SOURCEFILES += imr.c msg-bus.c
|
||||
CONTIKI_SOURCEFILES += stacks.c
|
||||
|
||||
ifneq ($(X86_CONF_PROT_DOMAINS),none)
|
||||
CONTIKI_SOURCEFILES += prot-domains.c $(X86_CONF_PROT_DOMAINS)-prot-domains.c imr-conf.c
|
||||
|
||||
ifeq ($(X86_CONF_PROT_DOMAINS),paging)
|
||||
LINKERSCRIPT_SFX = _paging
|
||||
X86_CONF_SYSCALLS_INT = 1
|
||||
ifeq ($(X86_CONF_USE_INVLPG),1)
|
||||
CFLAGS += -DX86_CONF_USE_INVLPG
|
||||
endif
|
||||
# This matches the definition of X86_CONF_PROT_DOMAINS__PAGING in prot-domains.h:
|
||||
CFLAGS += -DX86_CONF_PROT_DOMAINS=1
|
||||
else ifeq ($(X86_CONF_PROT_DOMAINS),tss)
|
||||
# This matches the definition of X86_CONF_PROT_DOMAINS__TSS in prot-domains.h:
|
||||
CFLAGS += -DX86_CONF_PROT_DOMAINS=2
|
||||
X86_CONF_MULTI_SEG = 1
|
||||
CONTIKI_SOURCEFILES += tss-prot-domains-asm.S
|
||||
else ifeq ($(X86_CONF_PROT_DOMAINS),swseg)
|
||||
# This matches the definition of X86_CONF_PROT_DOMAINS__SWSEG in prot-domains.h:
|
||||
CFLAGS += -DX86_CONF_PROT_DOMAINS=3
|
||||
X86_CONF_SYSCALLS_INT = 1
|
||||
X86_CONF_MULTI_SEG = 1
|
||||
else
|
||||
$(error Unrecognized setting for X86_CONF_PROT_DOMAINS: \
|
||||
$(X86_CONF_PROT_DOMAINS). See arch/cpu/x86/mm/README.md for \
|
||||
descriptions of available settings)
|
||||
endif
|
||||
|
||||
ifeq ($(X86_CONF_SYSCALLS_INT),1)
|
||||
CONTIKI_SOURCEFILES += syscalls-int-asm.S tss.c
|
||||
endif
|
||||
|
||||
ifeq ($(X86_CONF_MULTI_SEG),1)
|
||||
LINKERSCRIPT_SFX = _multi_seg
|
||||
CONTIKI_SOURCEFILES += multi-segment.c
|
||||
# Due to the way the multi-segment implementation of protection domains define
|
||||
# tightly-bounded stack segments, the base pointer register cannot be used as
|
||||
# a general-purpose register in all circumstances. The stack segment is used
|
||||
# by default for a data access that uses the base pointer as the base register
|
||||
# to compute the address. If the data referenced by the base pointer is not
|
||||
# on the stack, then the access will fail. Thus, it is necessary to disable
|
||||
# the omit-frame-pointer optimization. See mm/README.md for more details of
|
||||
# how multi-segment protection domains are implemented.
|
||||
CFLAGS += -fno-omit-frame-pointer
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
CFLAGS += -m32 -march=i586 -mtune=i586
|
||||
LDFLAGS += -m32 -Xlinker -T -Xlinker $(CONTIKI)/arch/cpu/x86/quarkX1000$(LINKERSCRIPT_SFX).ld
|
||||
# The C compiler is used to invoke the assembler, so the CFLAGS should be
|
||||
# passed to it on the command line:
|
||||
ASFLAGS = -c $(CFLAGS)
|
||||
|
||||
ifeq ($(X86_CONF_RESTRICT_DMA),1)
|
||||
CONTIKI_SOURCEFILES += imr-conf.c
|
||||
CFLAGS += -DX86_CONF_RESTRICT_DMA
|
||||
LDFLAGS += -Xlinker -T -Xlinker $(CONTIKI)/arch/cpu/x86/quarkX1000_dma.ld
|
||||
endif
|
||||
|
||||
### UEFI support
|
||||
|
||||
UEFI_DIR = $(CONTIKI_CPU)/uefi
|
||||
|
||||
ifndef EN_UEFI
|
||||
# Include a Makefile generated by the build_uefi.sh script, if available.
|
||||
# If that script was not run, then UEFI support will not be built.
|
||||
-include $(UEFI_DIR)/Makefile.uefi
|
||||
endif
|
||||
|
||||
ifeq ($(EN_UEFI),1)
|
||||
EDK2_DIR = $(UEFI_DIR)/edk2
|
||||
|
||||
GEN_FW = $(EDK2_DIR)/BaseTools/Source/C/bin/GenFw
|
||||
|
||||
CONTIKI_CPU_DIRS += uefi
|
||||
CONTIKI_SOURCEFILES += bootstrap_uefi.c
|
||||
CFLAGS += -I$(EDK2_DIR)/MdePkg/Include -I$(EDK2_DIR)/MdePkg/Include/Ia32
|
||||
else
|
||||
$(info Note: UEFI support is disabled.)
|
||||
$(info To enable UEFI support, run $(CONTIKI_CPU)/uefi/build_uefi.sh prior)
|
||||
$(info to building Contiki.)
|
||||
endif
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stacks.h"
|
||||
|
||||
# Multiboot
|
||||
.set MAGIC_NUMBER, 0x1BADB002
|
||||
.set FLAGS, 0x0
|
||||
.set CHECKSUM, -MAGIC_NUMBER
|
||||
|
||||
.section .multiboot
|
||||
.align 4
|
||||
.long MAGIC_NUMBER
|
||||
.long FLAGS
|
||||
.long CHECKSUM
|
||||
|
||||
.section .boot_text
|
||||
.global start
|
||||
start:
|
||||
cli
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS
|
||||
/* TSS-based protection domains use a multi-segment model that defines
|
||||
* tight bounds around stacks. That means that the bottom of the stack
|
||||
* has an offset of 0, which is the address of the stacks_main symbol.
|
||||
* The following code computes the physical load address of the top of
|
||||
* the stack, which is what should be initially used as the stack
|
||||
* pointer while the flat memory model is in use.
|
||||
*/
|
||||
lea _sdata_addr, %eax
|
||||
lea (stacks_main + STACKS_SIZE_MAIN)(%eax), %esp
|
||||
#else
|
||||
mov $(stacks_main + STACKS_SIZE_MAIN), %esp
|
||||
#endif
|
||||
call cpu_boot_stage0
|
|
@ -1,48 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DMA_H_
|
||||
#define CPU_X86_DMA_H_
|
||||
|
||||
#include "prot-domains.h"
|
||||
|
||||
#ifdef X86_CONF_RESTRICT_DMA
|
||||
#define ATTR_BSS_DMA __attribute__((section(".dma_bss")))
|
||||
#else
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE
|
||||
#define ATTR_BSS_DMA
|
||||
#else
|
||||
#define ATTR_BSS_DMA ATTR_BSS_META
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern int _ebss_pre_dma_addr, _sbss_dma_addr, _ebss_dma_addr;
|
||||
|
||||
#endif /* CPU_X86_DMA_H_ */
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#define NMI_ENABLE_PORT 0x70
|
||||
|
||||
void
|
||||
nmi_enable(void)
|
||||
{
|
||||
uint8_t value = inb(NMI_ENABLE_PORT);
|
||||
outb(NMI_ENABLE_PORT, value & ~BIT(8));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
nmi_disable(void)
|
||||
{
|
||||
uint8_t value = inb(NMI_ENABLE_PORT);
|
||||
outb(NMI_ENABLE_PORT, value | BIT(8));
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef NMI_H
|
||||
#define NMI_H
|
||||
|
||||
void nmi_enable(void);
|
||||
|
||||
void nmi_disable(void);
|
||||
|
||||
#endif /* NMI_H */
|
|
@ -1,280 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "pci.h"
|
||||
#include "helpers.h"
|
||||
#include "syscalls.h"
|
||||
|
||||
/* I/O port for PCI configuration address */
|
||||
#define PCI_CONFIG_ADDR_PORT 0xCF8
|
||||
/* I/O port for PCI configuration data */
|
||||
#define PCI_CONFIG_DATA_PORT 0xCFC
|
||||
|
||||
PROT_DOMAINS_ALLOC(dom_client_data_t, root_complex_drv);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Initialize PCI configuration register address in preparation for accessing
|
||||
* the specified register.
|
||||
*/
|
||||
static void
|
||||
set_addr(pci_config_addr_t addr)
|
||||
{
|
||||
addr.en_mapping = 1;
|
||||
|
||||
outl(PCI_CONFIG_ADDR_PORT, addr.raw);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Read from the specified PCI configuration register.
|
||||
* \param addr Address of PCI configuration register.
|
||||
* \return Value read from PCI configuration register.
|
||||
*/
|
||||
uint32_t
|
||||
pci_config_read(pci_config_addr_t addr)
|
||||
{
|
||||
set_addr(addr);
|
||||
|
||||
return inl(PCI_CONFIG_DATA_PORT);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Write to the PCI configuration data port.
|
||||
* \param addr Address of PCI configuration register.
|
||||
* \param data Value to write.
|
||||
*/
|
||||
void
|
||||
pci_config_write(pci_config_addr_t addr, uint32_t data)
|
||||
{
|
||||
set_addr(addr);
|
||||
|
||||
outl(PCI_CONFIG_DATA_PORT, data);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Enable PCI command bits of the specified PCI configuration
|
||||
* register.
|
||||
* \param addr Address of PCI configuration register.
|
||||
* \param flags Flags used to enable PCI command bits.
|
||||
*/
|
||||
void
|
||||
pci_command_enable(pci_config_addr_t addr, uint32_t flags)
|
||||
{
|
||||
uint32_t data;
|
||||
|
||||
addr.reg_off = 0x04; /* PCI COMMAND_REGISTER */
|
||||
|
||||
data = pci_config_read(addr);
|
||||
pci_config_write(addr, data | flags);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Set current PIRQ to interrupt queue agent. PCI based interrupts
|
||||
* PIRQ[A:H] are then available for consumption by either the 8259
|
||||
* PICs or the IO-APIC depending on configuration of the 8 PIRQx
|
||||
* Routing Control Registers PIRQ[A:H]. See also pci_pirq_set_irq().
|
||||
* \param agent Interrupt Queue Agent to be used, IRQAGENT[0:3].
|
||||
* \param pin Interrupt Pin Route to be used, INT[A:D].
|
||||
* \param pirq PIRQ to be used, PIRQ[A:H].
|
||||
*/
|
||||
SYSCALLS_DEFINE_SINGLETON(pci_irq_agent_set_pirq,
|
||||
root_complex_drv,
|
||||
IRQAGENT agent, INTR_PIN pin, PIRQ pirq)
|
||||
{
|
||||
uint16_t value;
|
||||
uint32_t rcba_addr, offset = 0;
|
||||
|
||||
rcba_addr = PROT_DOMAINS_MMIO(root_complex_drv);
|
||||
|
||||
assert(agent >= IRQAGENT0 && agent <= IRQAGENT3);
|
||||
assert(pin >= INTA && pin <= INTD);
|
||||
assert(pirq >= PIRQA && pirq <= PIRQH);
|
||||
|
||||
switch(agent) {
|
||||
case IRQAGENT0:
|
||||
if(pin != INTA) {
|
||||
halt();
|
||||
}
|
||||
offset = 0x3140;
|
||||
break;
|
||||
case IRQAGENT1:
|
||||
offset = 0x3142;
|
||||
break;
|
||||
case IRQAGENT2:
|
||||
if(pin != INTA) {
|
||||
halt();
|
||||
}
|
||||
offset = 0x3144;
|
||||
break;
|
||||
case IRQAGENT3:
|
||||
offset = 0x3146;
|
||||
}
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
|
||||
MMIO_READW(value, *(uint16_t ATTR_MMIO_ADDR_SPACE *)(rcba_addr + offset));
|
||||
|
||||
/* clear interrupt pin route and set corresponding pirq. */
|
||||
switch(pin) {
|
||||
case INTA:
|
||||
value &= ~0xF;
|
||||
value |= pirq;
|
||||
break;
|
||||
case INTB:
|
||||
value &= ~0xF0;
|
||||
value |= (pirq << 4);
|
||||
break;
|
||||
case INTC:
|
||||
value &= ~0xF00;
|
||||
value |= (pirq << 8);
|
||||
break;
|
||||
case INTD:
|
||||
value &= ~0xF000;
|
||||
value |= (pirq << 12);
|
||||
}
|
||||
|
||||
MMIO_WRITEW(*(uint16_t ATTR_MMIO_ADDR_SPACE *)(rcba_addr + offset), value);
|
||||
|
||||
prot_domains_disable_mmio();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Set current IRQ to PIRQ. The interrupt router can be
|
||||
* programmed to allow PIRQ[A:H] to be routed internally
|
||||
* to the 8259 as ISA compatible interrupts. See also
|
||||
* pci_irq_agent_set_pirq().
|
||||
* \param pirq PIRQ to be used, PIRQ[A:H].
|
||||
* \param pin IRQ to be used, IRQ[0:15].
|
||||
* \param route_to_legacy Whether or not the interrupt should be routed to PIC 8259.
|
||||
*/
|
||||
void
|
||||
pci_pirq_set_irq(PIRQ pirq, uint8_t irq, uint8_t route_to_legacy)
|
||||
{
|
||||
pci_config_addr_t pci;
|
||||
uint32_t value;
|
||||
|
||||
assert(pirq >= PIRQA && pirq <= PIRQH);
|
||||
assert(irq >= 0 && irq <= 0xF);
|
||||
assert(route_to_legacy == 0 || route_to_legacy == 1);
|
||||
|
||||
pci.raw = 0;
|
||||
pci.bus = 0;
|
||||
pci.dev = 31;
|
||||
pci.func = 0;
|
||||
pci.reg_off = (pirq <= PIRQD) ? 0x60 : 0x64; /* PABCDRC and PEFGHRC Registers */
|
||||
|
||||
value = pci_config_read(pci);
|
||||
|
||||
switch(pirq) {
|
||||
case PIRQA:
|
||||
case PIRQE:
|
||||
value &= ~0x8F;
|
||||
value |= irq;
|
||||
value |= (!route_to_legacy << 7);
|
||||
break;
|
||||
case PIRQB:
|
||||
case PIRQF:
|
||||
value &= ~0x8F00;
|
||||
value |= (irq << 8);
|
||||
value |= (!route_to_legacy << 15);
|
||||
break;
|
||||
case PIRQC:
|
||||
case PIRQG:
|
||||
value &= ~0x8F0000;
|
||||
value |= (irq << 16);
|
||||
value |= (!route_to_legacy << 23);
|
||||
break;
|
||||
case PIRQD:
|
||||
case PIRQH:
|
||||
value &= ~0x8F000000;
|
||||
value |= (irq << 24);
|
||||
value |= (!route_to_legacy << 31);
|
||||
}
|
||||
|
||||
set_addr(pci);
|
||||
outl(PCI_CONFIG_DATA_PORT, value);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Initialize a structure for a PCI device driver that performs
|
||||
* MMIO to address range 0. Assumes that device has already
|
||||
* been configured with an MMIO address range 0, e.g. by
|
||||
* firmware.
|
||||
* \param c_this Structure that will be initialized to represent the driver.
|
||||
* \param pci_addr PCI base address of device.
|
||||
* \param mmio_sz Size of MMIO region.
|
||||
* \param meta Base address of optional driver-defined metadata.
|
||||
* \param meta_sz Size of optional driver-defined metadata.
|
||||
*/
|
||||
void
|
||||
pci_init(pci_driver_t ATTR_KERN_ADDR_SPACE *c_this,
|
||||
pci_config_addr_t pci_addr,
|
||||
size_t mmio_sz,
|
||||
uintptr_t meta,
|
||||
size_t meta_sz)
|
||||
{
|
||||
uintptr_t mmio;
|
||||
|
||||
/* The BAR value is masked to clear non-address bits. */
|
||||
mmio = pci_config_read(pci_addr) & ~0xFFF;
|
||||
|
||||
prot_domains_reg(c_this, mmio, mmio_sz, meta, meta_sz, false);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Initialize the PCI root complex driver.
|
||||
*/
|
||||
void
|
||||
pci_root_complex_init(void)
|
||||
{
|
||||
uint32_t rcba_addr;
|
||||
pci_config_addr_t pci = { .raw = 0 };
|
||||
pci.dev = 31;
|
||||
pci.reg_off = 0xF0; /* Root Complex Base Address Register */
|
||||
|
||||
/* masked to clear non-address bits. */
|
||||
rcba_addr = pci_config_read(pci) & ~0x3FFF;
|
||||
|
||||
PROT_DOMAINS_INIT_ID(root_complex_drv);
|
||||
prot_domains_reg(&root_complex_drv, rcba_addr, 0x4000, 0, 0, false);
|
||||
SYSCALLS_INIT(pci_irq_agent_set_pirq);
|
||||
SYSCALLS_AUTHZ(pci_irq_agent_set_pirq, root_complex_drv);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Prevent further invocations of pci_irq_agent_set_pirq.
|
||||
*/
|
||||
void
|
||||
pci_root_complex_lock(void)
|
||||
{
|
||||
SYSCALLS_DEAUTHZ(pci_irq_agent_set_pirq, root_complex_drv);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_LEGACY_PC_PCI_H_
|
||||
#define CPU_X86_DRIVERS_LEGACY_PC_PCI_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "helpers.h"
|
||||
#include <stdlib.h>
|
||||
#include "prot-domains.h"
|
||||
|
||||
/** PCI configuration register identifier for Base Address Registers */
|
||||
#define PCI_CONFIG_REG_BAR0 0x10
|
||||
#define PCI_CONFIG_REG_BAR1 0x14
|
||||
|
||||
/** PCI Interrupt Routing is mapped using Interrupt Queue Agents */
|
||||
typedef enum {
|
||||
IRQAGENT0,
|
||||
IRQAGENT1,
|
||||
IRQAGENT2,
|
||||
IRQAGENT3
|
||||
} IRQAGENT;
|
||||
|
||||
/** PCI Interupt Pins */
|
||||
typedef enum {
|
||||
INTA,
|
||||
INTB,
|
||||
INTC,
|
||||
INTD
|
||||
} INTR_PIN;
|
||||
|
||||
/**
|
||||
* PCI based interrupts PIRQ[A:H] are then available for consumption by either
|
||||
* the 8259 PICs or the IO-APIC.
|
||||
*/
|
||||
typedef enum {
|
||||
PIRQA,
|
||||
PIRQB,
|
||||
PIRQC,
|
||||
PIRQD,
|
||||
PIRQE,
|
||||
PIRQF,
|
||||
PIRQG,
|
||||
PIRQH,
|
||||
} PIRQ;
|
||||
|
||||
/** PCI command register bit to enable bus mastering */
|
||||
#define PCI_CMD_2_BUS_MST_EN BIT(2)
|
||||
/** PCI command register bit to enable memory space */
|
||||
#define PCI_CMD_1_MEM_SPACE_EN BIT(1)
|
||||
|
||||
/**
|
||||
* PCI configuration address
|
||||
*
|
||||
* Refer to Intel Quark SoC X1000 Datasheet, Section 5.5 for more details on
|
||||
* PCI configuration register access.
|
||||
*/
|
||||
typedef union pci_config_addr {
|
||||
struct {
|
||||
/** Register/offset number. Least-significant two bits should be zero. */
|
||||
uint32_t reg_off : 8;
|
||||
uint32_t func : 3; /**< Function number */
|
||||
uint32_t dev : 5; /**< Device number */
|
||||
uint32_t bus : 8; /**< Bus number */
|
||||
uint32_t : 7;
|
||||
/** Must be set to perform PCI configuration access. */
|
||||
uint32_t en_mapping : 1;
|
||||
};
|
||||
uint32_t raw;
|
||||
} pci_config_addr_t;
|
||||
|
||||
uint32_t pci_config_read(pci_config_addr_t addr);
|
||||
void pci_config_write(pci_config_addr_t addr, uint32_t data);
|
||||
void pci_command_enable(pci_config_addr_t addr, uint32_t flags);
|
||||
|
||||
typedef dom_client_data_t pci_driver_t;
|
||||
|
||||
void pci_init(pci_driver_t ATTR_KERN_ADDR_SPACE *c_this,
|
||||
pci_config_addr_t pci_addr,
|
||||
size_t mmio_sz,
|
||||
uintptr_t meta,
|
||||
size_t meta_sz);
|
||||
void pci_irq_agent_set_pirq(IRQAGENT agent, INTR_PIN pin, PIRQ pirq);
|
||||
void pci_pirq_set_irq(PIRQ pirq, uint8_t irq, uint8_t route_to_legacy);
|
||||
void pci_root_complex_init(void);
|
||||
void pci_root_complex_lock(void);
|
||||
|
||||
#define PCI_MMIO_READL(c_this, dest, reg_addr) \
|
||||
MMIO_READL(dest, \
|
||||
*((volatile uint32_t ATTR_MMIO_ADDR_SPACE *) \
|
||||
(((uintptr_t)PROT_DOMAINS_MMIO(c_this)) + (reg_addr))))
|
||||
#define PCI_MMIO_WRITEL(c_this, reg_addr, src) \
|
||||
MMIO_WRITEL(*((volatile uint32_t ATTR_MMIO_ADDR_SPACE *) \
|
||||
(((uintptr_t)PROT_DOMAINS_MMIO(c_this)) + (reg_addr))), \
|
||||
src)
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_LEGACY_PC_PCI_H_ */
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "drivers/legacy_pc/pic.h"
|
||||
|
||||
#define PIC_ACK 0x20
|
||||
|
||||
void
|
||||
pic_unmask_irq(unsigned int num)
|
||||
{
|
||||
uint16_t port;
|
||||
uint8_t bitmap;
|
||||
|
||||
if(num <= 7) {
|
||||
port = PIC1_DATA_PORT;
|
||||
} else {
|
||||
port = PIC2_DATA_PORT;
|
||||
num -= 8;
|
||||
}
|
||||
|
||||
bitmap = inb(port);
|
||||
outb(port, bitmap & ~BIT(num));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
pic_eoi(unsigned int irq)
|
||||
{
|
||||
if(irq >= 8) {
|
||||
outb(PIC2_CMD_PORT, PIC_ACK);
|
||||
}
|
||||
|
||||
outb(PIC1_CMD_PORT, PIC_ACK);
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PIC_H
|
||||
#define PIC_H
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#define PIC1_CMD_PORT 0x20
|
||||
#define PIC1_DATA_PORT 0x21
|
||||
#define PIC2_CMD_PORT 0xA0
|
||||
#define PIC2_DATA_PORT 0xA1
|
||||
#define PIC1_OFFSET 0x20
|
||||
#define PIC2_OFFSET PIC1_OFFSET + 8
|
||||
|
||||
/*
|
||||
* Returns the actual interrupt number of a given IRQ,
|
||||
* no matter which PIC it is part of.
|
||||
*/
|
||||
#define PIC_INT(a) (a + PIC1_OFFSET)
|
||||
|
||||
void pic_unmask_irq(unsigned int num);
|
||||
|
||||
/* This function initializes the daisy-chained Master and Slave 8259 PICs.
|
||||
* It is only called once, so let's give the compiler the option to inline it.
|
||||
* For more information about the ICWs, please refer to http://stanislavs.org/helppc/8259.html.
|
||||
*/
|
||||
static inline void
|
||||
pic_init(void)
|
||||
{
|
||||
/* ICW1: Initialization. */
|
||||
outb(PIC1_CMD_PORT, 0x11);
|
||||
outb(PIC2_CMD_PORT, 0x11);
|
||||
|
||||
/* ICW2: Remap IRQs by setting an IDT Offset for each PIC. */
|
||||
outb(PIC1_DATA_PORT, PIC1_OFFSET);
|
||||
outb(PIC2_DATA_PORT, PIC2_OFFSET);
|
||||
|
||||
/* ICW3: Setup Slave to Master's IRQ2. */
|
||||
outb(PIC1_DATA_PORT, 0x04);
|
||||
outb(PIC2_DATA_PORT, 0x02);
|
||||
|
||||
/* ICW4: Environment setup. Set PIC1 as master and PIC2 as slave. */
|
||||
outb(PIC1_DATA_PORT, 0x01);
|
||||
outb(PIC2_DATA_PORT, 0x01);
|
||||
|
||||
/* Set the IMR register, masking all hardware interrupts but IRQ 2.
|
||||
* We will have to unmask each IRQ when registering them. */
|
||||
outb(PIC1_DATA_PORT, 0xfb);
|
||||
outb(PIC2_DATA_PORT, 0xff);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function sends an end-of-interrupt (EOI) to the correct PIC according
|
||||
* to the IRQ line number.
|
||||
*/
|
||||
void pic_eoi(unsigned int irq);
|
||||
|
||||
#endif /* PIC_H */
|
|
@ -1,80 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "drivers/legacy_pc/pic.h"
|
||||
#include "drivers/legacy_pc/pit.h"
|
||||
#include "helpers.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
/* PCs usually provide an 8254 PIT chip with maximum clock of 1.193182 MHz. */
|
||||
#define PIT_CONTROL_PORT 0x43
|
||||
#define PIT_COUNTER0_PORT 0x40
|
||||
#define PIT_CLOCK_FREQUENCY 1193182
|
||||
#define PIT_IRQ 0
|
||||
#define PIT_INT PIC_INT(PIT_IRQ)
|
||||
|
||||
static pit_int_callback interrupt_cb;
|
||||
|
||||
static void
|
||||
pit_int_handler(void)
|
||||
{
|
||||
interrupt_cb();
|
||||
|
||||
pic_eoi(PIT_IRQ);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
pit_init(uint32_t ticks_rate, pit_int_callback cb)
|
||||
{
|
||||
SET_INTERRUPT_HANDLER(PIT_INT, 0, pit_int_handler);
|
||||
|
||||
interrupt_cb = cb;
|
||||
|
||||
/* Calculate the 16bit divisor that can provide the chosen clock tick rate
|
||||
* (CLOCK_CONF_SECOND in contiki-conf.h). For reference --> tick rate = clock frequency / divisor.
|
||||
* If we provide an odd divisor to the Square Wave generator (Mode 3) of
|
||||
* the Counter0, the duty cycle won't be exactly 50%, so we always round
|
||||
* it to nearest even integer.
|
||||
*/
|
||||
uint16_t divisor = rint(PIT_CLOCK_FREQUENCY / ticks_rate);
|
||||
|
||||
/* Setup Control register flags in a didactic way. */
|
||||
uint8_t flags = 0x30; /* Set bits 7:6 to select Counter0 and 5:4 to select "write 7:0 bits first". */
|
||||
flags |= 0x6; /* Set bits 3:1 to Mode 3 and bit 0 to BCD off. */
|
||||
|
||||
outb(PIT_CONTROL_PORT, flags);
|
||||
|
||||
outb(PIT_COUNTER0_PORT, divisor & 0xFF); /* Write least significant bytes first. */
|
||||
outb(PIT_COUNTER0_PORT, (divisor >> 8) & 0xFF);
|
||||
|
||||
pic_unmask_irq(PIT_IRQ);
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PIT_H
|
||||
#define PIT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*pit_int_callback)(void);
|
||||
|
||||
/**
|
||||
* Initializes the 8254 Programmable Interrupt Timer chip (Counter 0 only).
|
||||
* The PIT Interrupt callback is implemented by the driver's users. It is
|
||||
* called from interrupt context, so it has to return as soon as possible.
|
||||
*/
|
||||
void pit_init(uint32_t ticks_rate, pit_int_callback c);
|
||||
|
||||
#endif /* PIT_H */
|
|
@ -1,95 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "drivers/legacy_pc/rtc.h"
|
||||
#include "drivers/legacy_pc/pic.h"
|
||||
#include "drivers/legacy_pc/nmi.h"
|
||||
#include "helpers.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
#define RTC_INDEX_REGISTER 0x70
|
||||
#define RTC_TARGET_REGISTER 0x71
|
||||
#define RTC_IRQ 8
|
||||
#define RTC_INT PIC_INT(RTC_IRQ)
|
||||
|
||||
static void (*user_callback)(void);
|
||||
|
||||
static void
|
||||
rtc_handler()
|
||||
{
|
||||
user_callback();
|
||||
|
||||
/* Clear Register C otherwise interrupts will not happen again.
|
||||
* Register C is automatically cleared when it is read so we do
|
||||
* a dummy read to clear it.
|
||||
*/
|
||||
outb(RTC_INDEX_REGISTER, 0x0C);
|
||||
inb(RTC_TARGET_REGISTER);
|
||||
|
||||
/* Issue the End of Interrupt to PIC */
|
||||
pic_eoi(RTC_IRQ);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Initialize the Real Time Clock.
|
||||
* @frequency: RTC has very specific values for frequency. They are: 2, 4, 8,
|
||||
* 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, and 8192 Hz.
|
||||
* value otherwise it will not work properly.
|
||||
* @callback: This callback is called every time the RTC IRQ is raised.
|
||||
* It is executed in interrupt context.
|
||||
*/
|
||||
void
|
||||
rtc_init(rtc_frequency_t frequency, void (*callback)(void))
|
||||
{
|
||||
uint8_t reg_a, reg_b;
|
||||
|
||||
user_callback = callback;
|
||||
|
||||
SET_INTERRUPT_HANDLER(RTC_INT, 0, rtc_handler);
|
||||
|
||||
nmi_disable();
|
||||
|
||||
/* Select interrupt period to 7.8125 ms */
|
||||
outb(RTC_INDEX_REGISTER, 0x8A);
|
||||
reg_a = inb(RTC_TARGET_REGISTER);
|
||||
reg_a &= 0xF0;
|
||||
reg_a |= frequency;
|
||||
outb(RTC_INDEX_REGISTER, 0x8A);
|
||||
outb(RTC_TARGET_REGISTER, reg_a);
|
||||
|
||||
/* Enable periodic interrupt */
|
||||
outb(RTC_INDEX_REGISTER, 0x8B);
|
||||
reg_b = inb(RTC_TARGET_REGISTER);
|
||||
outb(RTC_INDEX_REGISTER, 0x8B);
|
||||
outb(RTC_TARGET_REGISTER, reg_b | BIT(6));
|
||||
|
||||
nmi_enable();
|
||||
|
||||
pic_unmask_irq(RTC_IRQ);
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RTC_H
|
||||
#define RTC_H
|
||||
|
||||
typedef enum {
|
||||
RTC_8192_HZ = 2,
|
||||
RTC_4096_HZ = 3,
|
||||
RTC_2048_HZ = 4,
|
||||
RTC_1024_HZ = 5,
|
||||
RTC_512_HZ = 6,
|
||||
RTC_256_HZ = 7,
|
||||
RTC_128_HZ = 8,
|
||||
RTC_64_HZ = 9,
|
||||
RTC_32_HZ = 10,
|
||||
RTC_16_HZ = 11,
|
||||
RTC_8_HZ = 12,
|
||||
RTC_4_HZ = 13,
|
||||
RTC_2_HZ = 14,
|
||||
} rtc_frequency_t;
|
||||
|
||||
void rtc_init(rtc_frequency_t frequency, void (*callback)(void));
|
||||
|
||||
#endif /* RTC_H */
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "idt.h"
|
||||
#include "interrupt.h"
|
||||
#include "pic.h"
|
||||
#include "shared-isr.h"
|
||||
|
||||
/* Defined in linker script */
|
||||
extern shared_isr_client_t _sdata_shared_isr, _edata_shared_isr;
|
||||
|
||||
static void __attribute__((used))
|
||||
shared_handler(void)
|
||||
{
|
||||
shared_isr_client_t *client;
|
||||
for(client = &_sdata_shared_isr; client < &_edata_shared_isr; client++) {
|
||||
if(client->handler()) {
|
||||
pic_eoi(client->irq);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialize shared ISR by iterating through all of its clients and
|
||||
* configuring their interrupts to route to the shared ISR.
|
||||
*/
|
||||
void
|
||||
shared_isr_init(void)
|
||||
{
|
||||
shared_isr_client_t *client = &_sdata_shared_isr;
|
||||
shared_isr_client_t *consistency_check_client;
|
||||
bool prev_conf;
|
||||
|
||||
void shared_isr_stub(void);
|
||||
__asm__ __volatile__ (
|
||||
ISR_STUB("shared_isr_stub", 0, "shared_handler", 0)
|
||||
:
|
||||
);
|
||||
|
||||
while(client < &_edata_shared_isr) {
|
||||
consistency_check_client = &_sdata_shared_isr;
|
||||
|
||||
prev_conf = false;
|
||||
|
||||
while(consistency_check_client < client) {
|
||||
if((client->irq == consistency_check_client->irq) ||
|
||||
(client->pin == consistency_check_client->pin) ||
|
||||
(client->pirq == consistency_check_client->pirq)) {
|
||||
|
||||
prev_conf = true;
|
||||
|
||||
/* This interrupt was previously configured. */
|
||||
break;
|
||||
}
|
||||
|
||||
consistency_check_client++;
|
||||
}
|
||||
|
||||
if(prev_conf) {
|
||||
/* The requested configurations for each IRQ must be consistent. */
|
||||
assert((client->irq == consistency_check_client->irq) &&
|
||||
(client->agent == consistency_check_client->agent) &&
|
||||
(client->pin == consistency_check_client->pin) &&
|
||||
(client->pirq == consistency_check_client->pirq));
|
||||
} else {
|
||||
idt_set_intr_gate_desc(PIC_INT(client->irq), (uint32_t)shared_isr_stub,
|
||||
GDT_SEL_CODE_INT, PRIV_LVL_INT);
|
||||
|
||||
pci_irq_agent_set_pirq(client->agent, client->pin, client->pirq);
|
||||
|
||||
pci_pirq_set_irq(client->pirq, client->irq, 1);
|
||||
|
||||
pic_unmask_irq(client->irq);
|
||||
}
|
||||
|
||||
client++;
|
||||
}
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_LEGACY_PC_SHARED_ISR_H_
|
||||
#define CPU_X86_DRIVERS_LEGACY_PC_SHARED_ISR_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "pci.h"
|
||||
|
||||
/**
|
||||
* The handler function should return true if and only if it handled the
|
||||
* interrupt.
|
||||
*/
|
||||
typedef bool (*shared_isr_handler_t)(void);
|
||||
|
||||
typedef struct shared_isr_client {
|
||||
uint8_t irq;
|
||||
IRQAGENT agent;
|
||||
INTR_PIN pin;
|
||||
PIRQ pirq;
|
||||
shared_isr_handler_t handler;
|
||||
} shared_isr_client_t;
|
||||
|
||||
/* Unlike a non-shared interrupt handler function, an individual interrupt
|
||||
* handler for a shared interrupt must not issue an EOI. The EOI is issued by
|
||||
* the shared-isr subsystem.
|
||||
*/
|
||||
#define DEFINE_SHARED_IRQ(irq_, agent_, pin_, pirq_, handler_) \
|
||||
static struct shared_isr_client \
|
||||
__attribute__((used, section(".shared_isr_data"))) _shared_irq_##irq_ = { \
|
||||
.irq = irq_, \
|
||||
.agent = agent_, \
|
||||
.pin = pin_, \
|
||||
.pirq = pirq_, \
|
||||
.handler = handler_ \
|
||||
}
|
||||
|
||||
void shared_isr_init(void);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_LEGACY_PC_SHARED_ISR_H_ */
|
|
@ -1,179 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "helpers.h"
|
||||
#include "paging.h"
|
||||
#include "prot-domains.h"
|
||||
#include "syscalls.h"
|
||||
#include "uart-16x50.h"
|
||||
|
||||
/* Refer to Intel Quark SoC X1000 Datasheet, Chapter 18 for more details on
|
||||
* UART operation.
|
||||
*/
|
||||
|
||||
/* Divisor Latch Access Bit (DLAB) mask for Line Control Register (LCR).
|
||||
*
|
||||
* When bit is set, enables access to divisor registers to set baud rate. When
|
||||
* clear, enables access to other registers mapped to the same addresses as the
|
||||
* divisor registers.
|
||||
*/
|
||||
#define UART_LCR_7_DLAB BIT(7)
|
||||
/* Setting for LCR that configures the UART to operate with no parity, 1 stop
|
||||
* bit, and eight bits per character.
|
||||
*/
|
||||
#define UART_LCR_8BITS 0x03
|
||||
|
||||
/* FIFO Control Register (FCR) bitmasks */
|
||||
#define UART_FCR_0_FIFOE BIT(0) /*< enable FIFOs */
|
||||
#define UART_FCR_1_RFIFOR BIT(1) /*< reset RX FIFO */
|
||||
#define UART_FCR_2_XFIFOR BIT(2) /*< reset TX FIFO */
|
||||
|
||||
/* Line Status Register (LSR) Transmit Holding Register Empty bitmask to check
|
||||
* whether the Transmit Holding Register (THR) or TX FIFO is empty.
|
||||
*/
|
||||
#define UART_LSR_5_THRE BIT(5)
|
||||
|
||||
/* MMIO registers for UART */
|
||||
typedef struct uart_16x50_regs {
|
||||
volatile uint32_t rbr_thr_dll, ier_dlh, iir_fcr, lcr;
|
||||
volatile uint32_t mcr, lsr, msr, scr, usr, htx, dmasa;
|
||||
} uart_16x50_regs_t;
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
|
||||
/* When paging-based protection domains are in use, at least one page of memory
|
||||
* must be reserved to facilitate access to the MMIO region, since that is the
|
||||
* smallest unit of memory that can be managed with paging:
|
||||
*/
|
||||
#define UART_MMIO_SZ MIN_PAGE_SIZE
|
||||
#else
|
||||
/* Multi-segment protection domain implementations can control memory with
|
||||
* byte granularity. Thus, only the registers defined in the uart_16x50_regs
|
||||
* structure are included in the MMIO region allocated for this protection
|
||||
* domain:
|
||||
*/
|
||||
#define UART_MMIO_SZ sizeof(uart_16x50_regs_t)
|
||||
#endif
|
||||
|
||||
void uart_16x50_setup(uart_16x50_driver_t c_this, uint16_t dl);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
SYSCALLS_DEFINE(uart_16x50_setup, uart_16x50_driver_t c_this, uint16_t dl)
|
||||
{
|
||||
uart_16x50_regs_t ATTR_MMIO_ADDR_SPACE *regs =
|
||||
(uart_16x50_regs_t ATTR_MMIO_ADDR_SPACE *)PROT_DOMAINS_MMIO(c_this);
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
|
||||
/* Set the DLAB bit to enable access to divisor settings. */
|
||||
MMIO_WRITEL(regs->lcr, UART_LCR_7_DLAB);
|
||||
|
||||
/* The divisor settings configure the baud rate, and may need to be defined
|
||||
* on a per-device basis.
|
||||
*/
|
||||
MMIO_WRITEL(regs->rbr_thr_dll, dl & UINT8_MAX);
|
||||
MMIO_WRITEL(regs->ier_dlh, dl >> 8);
|
||||
|
||||
/* Clear the DLAB bit to enable access to other settings and configure other
|
||||
* UART parameters.
|
||||
*/
|
||||
MMIO_WRITEL(regs->lcr, UART_LCR_8BITS);
|
||||
|
||||
/* Enable the FIFOs. */
|
||||
MMIO_WRITEL(regs->iir_fcr,
|
||||
UART_FCR_0_FIFOE | UART_FCR_1_RFIFOR | UART_FCR_2_XFIFOR);
|
||||
|
||||
prot_domains_disable_mmio();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Transmit a character through a UART.
|
||||
* \param c_this Initialized structure representing the device.
|
||||
* \param c Character to be transmitted.
|
||||
*
|
||||
* This procedure will block indefinitely until the UART is ready
|
||||
* to accept the character to be transmitted.
|
||||
*/
|
||||
SYSCALLS_DEFINE(uart_16x50_tx, uart_16x50_driver_t c_this, uint8_t c)
|
||||
{
|
||||
uint32_t ready;
|
||||
uart_16x50_regs_t ATTR_MMIO_ADDR_SPACE *regs =
|
||||
(uart_16x50_regs_t ATTR_MMIO_ADDR_SPACE *)PROT_DOMAINS_MMIO(c_this);
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
|
||||
/* Wait for space in TX FIFO. */
|
||||
do {
|
||||
MMIO_READL(ready, regs->lsr);
|
||||
} while((ready & UART_LSR_5_THRE) == 0);
|
||||
|
||||
/* Add character to TX FIFO. */
|
||||
MMIO_WRITEL(regs->rbr_thr_dll, c);
|
||||
|
||||
prot_domains_disable_mmio();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Perform common initialization that must precede per-port
|
||||
* initialization.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
uart_16x50_init(void)
|
||||
{
|
||||
SYSCALLS_INIT(uart_16x50_setup);
|
||||
SYSCALLS_INIT(uart_16x50_tx);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Initialize an MMIO-programmable 16X50 UART.
|
||||
* \param c_this Structure that will be initialized to represent the device.
|
||||
* \param pci_addr PCI address of device.
|
||||
* \param dl Divisor setting to configure the baud rate.
|
||||
*/
|
||||
void
|
||||
uart_16x50_init_port(uart_16x50_driver_t ATTR_KERN_ADDR_SPACE *c_this,
|
||||
pci_config_addr_t pci_addr,
|
||||
uint16_t dl)
|
||||
{
|
||||
uart_16x50_driver_t loc_c_this;
|
||||
|
||||
/* This assumes that the UART had an MMIO range assigned to it by the
|
||||
* firmware during boot.
|
||||
*/
|
||||
pci_init(c_this, pci_addr, UART_MMIO_SZ, 0, 0);
|
||||
SYSCALLS_AUTHZ(uart_16x50_setup, *c_this);
|
||||
SYSCALLS_AUTHZ(uart_16x50_tx, *c_this);
|
||||
|
||||
prot_domains_copy_dcd(&loc_c_this, c_this);
|
||||
|
||||
uart_16x50_setup(loc_c_this, dl);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_LEGACY_PC_UART_16X50_H_
|
||||
#define CPU_X86_DRIVERS_LEGACY_PC_UART_16X50_H_
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
typedef pci_driver_t uart_16x50_driver_t;
|
||||
|
||||
void uart_16x50_init(void);
|
||||
|
||||
void uart_16x50_init_port(uart_16x50_driver_t ATTR_KERN_ADDR_SPACE *c_this,
|
||||
pci_config_addr_t pci_addr,
|
||||
uint16_t dl);
|
||||
|
||||
void uart_16x50_tx(uart_16x50_driver_t c_this, uint8_t c);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_LEGACY_PC_UART_16X50_H_ */
|
|
@ -1,465 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "contiki-net.h"
|
||||
#include "dma.h"
|
||||
#include "eth.h"
|
||||
#include "helpers.h"
|
||||
#include "syscalls.h"
|
||||
#include "net/ip/uip.h"
|
||||
#include "pci.h"
|
||||
|
||||
typedef pci_driver_t quarkX1000_eth_driver_t;
|
||||
|
||||
/* Refer to Intel Quark SoC X1000 Datasheet, Chapter 15 for more details on
|
||||
* Ethernet device operation.
|
||||
*
|
||||
* This driver puts the Ethernet device into a very simple and space-efficient
|
||||
* mode of operation. It only allocates a single packet descriptor for each of
|
||||
* the transmit and receive directions, computes checksums on the CPU, and
|
||||
* enables store-and-forward mode for both transmit and receive directions.
|
||||
*/
|
||||
|
||||
/* Transmit descriptor */
|
||||
typedef struct quarkX1000_eth_tx_desc {
|
||||
/* First word of transmit descriptor */
|
||||
union {
|
||||
struct {
|
||||
/* Only valid in half-duplex mode. */
|
||||
uint32_t deferred_bit : 1;
|
||||
uint32_t err_underflow : 1;
|
||||
uint32_t err_excess_defer : 1;
|
||||
uint32_t coll_cnt_slot_num : 4;
|
||||
uint32_t vlan_frm : 1;
|
||||
uint32_t err_excess_coll : 1;
|
||||
uint32_t err_late_coll : 1;
|
||||
uint32_t err_no_carrier : 1;
|
||||
uint32_t err_carrier_loss : 1;
|
||||
uint32_t err_ip_payload : 1;
|
||||
uint32_t err_frm_flushed : 1;
|
||||
uint32_t err_jabber_tout : 1;
|
||||
/* OR of all other error bits. */
|
||||
uint32_t err_summary : 1;
|
||||
uint32_t err_ip_hdr : 1;
|
||||
uint32_t tx_timestamp_stat : 1;
|
||||
uint32_t vlan_ins_ctrl : 2;
|
||||
uint32_t addr2_chained : 1;
|
||||
uint32_t tx_end_of_ring : 1;
|
||||
uint32_t chksum_ins_ctrl : 2;
|
||||
uint32_t replace_crc : 1;
|
||||
uint32_t tx_timestamp_en : 1;
|
||||
uint32_t dis_pad : 1;
|
||||
uint32_t dis_crc : 1;
|
||||
uint32_t first_seg_in_frm : 1;
|
||||
uint32_t last_seg_in_frm : 1;
|
||||
uint32_t intr_on_complete : 1;
|
||||
/* When set, descriptor is owned by DMA. */
|
||||
uint32_t own : 1;
|
||||
};
|
||||
uint32_t tdes0;
|
||||
};
|
||||
/* Second word of transmit descriptor */
|
||||
union {
|
||||
struct {
|
||||
uint32_t tx_buf1_sz : 13;
|
||||
uint32_t : 3;
|
||||
uint32_t tx_buf2_sz : 13;
|
||||
uint32_t src_addr_ins_ctrl : 3;
|
||||
};
|
||||
uint32_t tdes1;
|
||||
};
|
||||
/* Pointer to frame data buffer */
|
||||
uint8_t *buf1_ptr;
|
||||
/* Unused, since this driver initializes only a single descriptor for each
|
||||
* direction.
|
||||
*/
|
||||
uint8_t *buf2_ptr;
|
||||
} quarkX1000_eth_tx_desc_t;
|
||||
|
||||
/* Transmit descriptor */
|
||||
typedef struct quarkX1000_eth_rx_desc {
|
||||
/* First word of receive descriptor */
|
||||
union {
|
||||
struct {
|
||||
uint32_t ext_stat : 1;
|
||||
uint32_t err_crc : 1;
|
||||
uint32_t err_dribble_bit : 1;
|
||||
uint32_t err_rx_mii : 1;
|
||||
uint32_t err_rx_wdt : 1;
|
||||
uint32_t frm_type : 1;
|
||||
uint32_t err_late_coll : 1;
|
||||
uint32_t giant_frm : 1;
|
||||
uint32_t last_desc : 1;
|
||||
uint32_t first_desc : 1;
|
||||
uint32_t vlan_tag : 1;
|
||||
uint32_t err_overflow : 1;
|
||||
uint32_t length_err : 1;
|
||||
uint32_t s_addr_filt_fail : 1;
|
||||
uint32_t err_desc : 1;
|
||||
uint32_t err_summary : 1;
|
||||
uint32_t frm_len : 14;
|
||||
uint32_t d_addr_filt_fail : 1;
|
||||
uint32_t own : 1;
|
||||
};
|
||||
uint32_t rdes0;
|
||||
};
|
||||
/* Second word of receive descriptor */
|
||||
union {
|
||||
struct {
|
||||
uint32_t rx_buf1_sz : 13;
|
||||
uint32_t : 1;
|
||||
uint32_t addr2_chained : 1;
|
||||
uint32_t rx_end_of_ring : 1;
|
||||
uint32_t rx_buf2_sz : 13;
|
||||
uint32_t : 2;
|
||||
uint32_t dis_int_compl : 1;
|
||||
};
|
||||
uint32_t rdes1;
|
||||
};
|
||||
/* Pointer to frame data buffer */
|
||||
uint8_t *buf1_ptr;
|
||||
/* Unused, since this driver initializes only a single descriptor for each
|
||||
* direction.
|
||||
*/
|
||||
uint8_t *buf2_ptr;
|
||||
} quarkX1000_eth_rx_desc_t;
|
||||
|
||||
/* Driver metadata associated with each Ethernet device */
|
||||
typedef struct quarkX1000_eth_meta {
|
||||
/* Transmit descriptor */
|
||||
volatile quarkX1000_eth_tx_desc_t tx_desc;
|
||||
/* Transmit DMA packet buffer */
|
||||
volatile uint8_t tx_buf[ALIGN(UIP_BUFSIZE, 4)];
|
||||
/* Receive descriptor */
|
||||
volatile quarkX1000_eth_rx_desc_t rx_desc;
|
||||
/* Receive DMA packet buffer */
|
||||
volatile uint8_t rx_buf[ALIGN(UIP_BUFSIZE, 4)];
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
|
||||
/* Domain-defined metadata must fill an even number of pages, since that is
|
||||
* the minimum granularity of access control supported by paging. However,
|
||||
* using the "aligned(4096)" attribute causes the alignment of the kernel
|
||||
* data section to increase, which causes problems when generating UEFI
|
||||
* binaries, as is described in the linker script. Thus, it is necessary
|
||||
* to manually pad the structure to fill a page. This only works if the
|
||||
* sizes of the actual fields of the structure are collectively less than a
|
||||
* page.
|
||||
*/
|
||||
uint8_t pad[MIN_PAGE_SIZE -
|
||||
(sizeof(quarkX1000_eth_tx_desc_t) +
|
||||
ALIGN(UIP_BUFSIZE, 4) +
|
||||
sizeof(quarkX1000_eth_rx_desc_t) +
|
||||
ALIGN(UIP_BUFSIZE, 4))];
|
||||
#endif
|
||||
} __attribute__((packed)) quarkX1000_eth_meta_t;
|
||||
|
||||
#define LOG_PFX "quarkX1000_eth: "
|
||||
|
||||
#define MMIO_SZ 0x2000
|
||||
|
||||
#define MAC_CONF_14_RMII_100M BIT(14)
|
||||
#define MAC_CONF_11_DUPLEX BIT(11)
|
||||
#define MAC_CONF_3_TX_EN BIT(3)
|
||||
#define MAC_CONF_2_RX_EN BIT(2)
|
||||
|
||||
#define OP_MODE_25_RX_STORE_N_FORWARD BIT(25)
|
||||
#define OP_MODE_21_TX_STORE_N_FORWARD BIT(21)
|
||||
#define OP_MODE_13_START_TX BIT(13)
|
||||
#define OP_MODE_1_START_RX BIT(1)
|
||||
|
||||
#define REG_ADDR_MAC_CONF 0x0000
|
||||
#define REG_ADDR_MACADDR_HI 0x0040
|
||||
#define REG_ADDR_MACADDR_LO 0x0044
|
||||
#define REG_ADDR_TX_POLL_DEMAND 0x1004
|
||||
#define REG_ADDR_RX_POLL_DEMAND 0x1008
|
||||
#define REG_ADDR_RX_DESC_LIST 0x100C
|
||||
#define REG_ADDR_TX_DESC_LIST 0x1010
|
||||
#define REG_ADDR_DMA_OPERATION 0x1018
|
||||
|
||||
PROT_DOMAINS_ALLOC(quarkX1000_eth_driver_t, drv);
|
||||
static quarkX1000_eth_meta_t ATTR_BSS_DMA meta;
|
||||
|
||||
void quarkX1000_eth_setup(uintptr_t meta_phys_base);
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
SYSCALLS_DEFINE_SINGLETON(quarkX1000_eth_setup, drv, uintptr_t meta_phys_base)
|
||||
{
|
||||
uip_eth_addr mac_addr;
|
||||
uint32_t mac_tmp1, mac_tmp2;
|
||||
quarkX1000_eth_rx_desc_t rx_desc;
|
||||
quarkX1000_eth_tx_desc_t tx_desc;
|
||||
quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *loc_meta =
|
||||
(quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *)PROT_DOMAINS_META(drv);
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
|
||||
/* Read the MAC address from the device. */
|
||||
PCI_MMIO_READL(drv, mac_tmp1, REG_ADDR_MACADDR_HI);
|
||||
PCI_MMIO_READL(drv, mac_tmp2, REG_ADDR_MACADDR_LO);
|
||||
|
||||
prot_domains_disable_mmio();
|
||||
|
||||
/* Convert the data read from the device into the format expected by
|
||||
* Contiki.
|
||||
*/
|
||||
mac_addr.addr[5] = (uint8_t)(mac_tmp1 >> 8);
|
||||
mac_addr.addr[4] = (uint8_t)mac_tmp1;
|
||||
mac_addr.addr[3] = (uint8_t)(mac_tmp2 >> 24);
|
||||
mac_addr.addr[2] = (uint8_t)(mac_tmp2 >> 16);
|
||||
mac_addr.addr[1] = (uint8_t)(mac_tmp2 >> 8);
|
||||
mac_addr.addr[0] = (uint8_t)mac_tmp2;
|
||||
|
||||
printf(LOG_PFX "MAC address = %02x:%02x:%02x:%02x:%02x:%02x.\n",
|
||||
mac_addr.addr[0],
|
||||
mac_addr.addr[1],
|
||||
mac_addr.addr[2],
|
||||
mac_addr.addr[3],
|
||||
mac_addr.addr[4],
|
||||
mac_addr.addr[5]
|
||||
);
|
||||
|
||||
uip_setethaddr(mac_addr);
|
||||
|
||||
/* Initialize transmit descriptor. */
|
||||
tx_desc.tdes0 = 0;
|
||||
tx_desc.tdes1 = 0;
|
||||
|
||||
tx_desc.tx_end_of_ring = 1;
|
||||
tx_desc.first_seg_in_frm = 1;
|
||||
tx_desc.last_seg_in_frm = 1;
|
||||
tx_desc.tx_end_of_ring = 1;
|
||||
|
||||
META_WRITEL(loc_meta->tx_desc.tdes0, tx_desc.tdes0);
|
||||
META_WRITEL(loc_meta->tx_desc.tdes1, tx_desc.tdes1);
|
||||
META_WRITEL(loc_meta->tx_desc.buf1_ptr,
|
||||
(uint8_t *)PROT_DOMAINS_META_OFF_TO_PHYS(
|
||||
(uintptr_t)&loc_meta->tx_buf, meta_phys_base));
|
||||
META_WRITEL(loc_meta->tx_desc.buf2_ptr, 0);
|
||||
|
||||
/* Initialize receive descriptor. */
|
||||
rx_desc.rdes0 = 0;
|
||||
rx_desc.rdes1 = 0;
|
||||
|
||||
rx_desc.own = 1;
|
||||
rx_desc.first_desc = 1;
|
||||
rx_desc.last_desc = 1;
|
||||
rx_desc.rx_buf1_sz = UIP_BUFSIZE;
|
||||
rx_desc.rx_end_of_ring = 1;
|
||||
|
||||
META_WRITEL(loc_meta->rx_desc.rdes0, rx_desc.rdes0);
|
||||
META_WRITEL(loc_meta->rx_desc.rdes1, rx_desc.rdes1);
|
||||
META_WRITEL(loc_meta->rx_desc.buf1_ptr,
|
||||
(uint8_t *)PROT_DOMAINS_META_OFF_TO_PHYS(
|
||||
(uintptr_t)&loc_meta->rx_buf, meta_phys_base));
|
||||
META_WRITEL(loc_meta->rx_desc.buf2_ptr, 0);
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
|
||||
/* Install transmit and receive descriptors. */
|
||||
PCI_MMIO_WRITEL(drv, REG_ADDR_RX_DESC_LIST,
|
||||
PROT_DOMAINS_META_OFF_TO_PHYS(
|
||||
(uintptr_t)&loc_meta->rx_desc, meta_phys_base));
|
||||
PCI_MMIO_WRITEL(drv, REG_ADDR_TX_DESC_LIST,
|
||||
PROT_DOMAINS_META_OFF_TO_PHYS(
|
||||
(uintptr_t)&loc_meta->tx_desc, meta_phys_base));
|
||||
|
||||
PCI_MMIO_WRITEL(drv, REG_ADDR_MAC_CONF,
|
||||
/* Set the RMII speed to 100Mbps */
|
||||
MAC_CONF_14_RMII_100M |
|
||||
/* Enable full-duplex mode */
|
||||
MAC_CONF_11_DUPLEX |
|
||||
/* Enable transmitter */
|
||||
MAC_CONF_3_TX_EN |
|
||||
/* Enable receiver */
|
||||
MAC_CONF_2_RX_EN);
|
||||
|
||||
PCI_MMIO_WRITEL(drv, REG_ADDR_DMA_OPERATION,
|
||||
/* Enable receive store-and-forward mode for simplicity. */
|
||||
OP_MODE_25_RX_STORE_N_FORWARD |
|
||||
/* Enable transmit store-and-forward mode for simplicity. */
|
||||
OP_MODE_21_TX_STORE_N_FORWARD |
|
||||
/* Place the transmitter state machine in the Running
|
||||
state. */
|
||||
OP_MODE_13_START_TX |
|
||||
/* Place the receiver state machine in the Running state. */
|
||||
OP_MODE_1_START_RX);
|
||||
|
||||
prot_domains_disable_mmio();
|
||||
|
||||
printf(LOG_PFX "Enabled 100M full-duplex mode.\n");
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Poll for a received Ethernet frame.
|
||||
* \param frame_len Will be set to the size of the received Ethernet frame or
|
||||
* zero if no frame is available.
|
||||
*
|
||||
* If a frame is received, this procedure copies it into the
|
||||
* global uip_buf buffer.
|
||||
*/
|
||||
SYSCALLS_DEFINE_SINGLETON(quarkX1000_eth_poll, drv, uint16_t * frame_len)
|
||||
{
|
||||
uint16_t *loc_frame_len;
|
||||
uint16_t frm_len = 0;
|
||||
quarkX1000_eth_rx_desc_t tmp_desc;
|
||||
quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *loc_meta =
|
||||
(quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *)PROT_DOMAINS_META(drv);
|
||||
|
||||
PROT_DOMAINS_VALIDATE_PTR(loc_frame_len, frame_len, sizeof(*frame_len));
|
||||
|
||||
META_READL(tmp_desc.rdes0, loc_meta->rx_desc.rdes0);
|
||||
|
||||
/* Check whether the RX descriptor is still owned by the device. If not,
|
||||
* process the received frame or an error that may have occurred.
|
||||
*/
|
||||
if(tmp_desc.own == 0) {
|
||||
META_READL(tmp_desc.rdes1, loc_meta->rx_desc.rdes1);
|
||||
if(tmp_desc.err_summary) {
|
||||
fprintf(stderr,
|
||||
LOG_PFX "Error receiving frame: RDES0 = %08x, RDES1 = %08x.\n",
|
||||
tmp_desc.rdes0, tmp_desc.rdes1);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
frm_len = tmp_desc.frm_len;
|
||||
assert(frm_len <= UIP_BUFSIZE);
|
||||
MEMCPY_FROM_META(uip_buf, loc_meta->rx_buf, frm_len);
|
||||
|
||||
/* Return ownership of the RX descriptor to the device. */
|
||||
tmp_desc.own = 1;
|
||||
|
||||
META_WRITEL(loc_meta->rx_desc.rdes0, tmp_desc.rdes0);
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
|
||||
/* Request that the device check for an available RX descriptor, since
|
||||
* ownership of the descriptor was just transferred to the device.
|
||||
*/
|
||||
PCI_MMIO_WRITEL(drv, REG_ADDR_RX_POLL_DEMAND, 1);
|
||||
|
||||
prot_domains_disable_mmio();
|
||||
}
|
||||
|
||||
*loc_frame_len = frm_len;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Transmit the current Ethernet frame.
|
||||
*
|
||||
* This procedure will block indefinitely until the Ethernet device is
|
||||
* ready to accept a new outgoing frame. It then copies the current
|
||||
* Ethernet frame from the global uip_buf buffer to the device DMA
|
||||
* buffer and signals to the device that a new frame is available to be
|
||||
* transmitted.
|
||||
*/
|
||||
SYSCALLS_DEFINE_SINGLETON(quarkX1000_eth_send, drv)
|
||||
{
|
||||
quarkX1000_eth_tx_desc_t tmp_desc;
|
||||
quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *loc_meta =
|
||||
(quarkX1000_eth_meta_t ATTR_META_ADDR_SPACE *)PROT_DOMAINS_META(drv);
|
||||
|
||||
/* Wait until the TX descriptor is no longer owned by the device. */
|
||||
do {
|
||||
META_READL(tmp_desc.tdes0, loc_meta->tx_desc.tdes0);
|
||||
} while(tmp_desc.own == 1);
|
||||
|
||||
META_READL(tmp_desc.tdes1, loc_meta->tx_desc.tdes1);
|
||||
|
||||
/* Check whether an error occurred transmitting the previous frame. */
|
||||
if(tmp_desc.err_summary) {
|
||||
fprintf(stderr,
|
||||
LOG_PFX "Error transmitting frame: TDES0 = %08x, TDES1 = %08x.\n",
|
||||
tmp_desc.tdes0, tmp_desc.tdes1);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* Transmit the next frame. */
|
||||
assert(uip_len <= UIP_BUFSIZE);
|
||||
MEMCPY_TO_META(loc_meta->tx_buf, uip_buf, uip_len);
|
||||
|
||||
tmp_desc.tx_buf1_sz = uip_len;
|
||||
|
||||
META_WRITEL(loc_meta->tx_desc.tdes1, tmp_desc.tdes1);
|
||||
|
||||
tmp_desc.own = 1;
|
||||
|
||||
META_WRITEL(loc_meta->tx_desc.tdes0, tmp_desc.tdes0);
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
|
||||
/* Request that the device check for an available TX descriptor, since
|
||||
* ownership of the descriptor was just transferred to the device.
|
||||
*/
|
||||
PCI_MMIO_WRITEL(drv, REG_ADDR_TX_POLL_DEMAND, 1);
|
||||
|
||||
prot_domains_disable_mmio();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Initialize the first Quark X1000 Ethernet MAC.
|
||||
*
|
||||
* This procedure assumes that an MMIO range for the device was
|
||||
* previously assigned, e.g. by firmware.
|
||||
*/
|
||||
void
|
||||
quarkX1000_eth_init(void)
|
||||
{
|
||||
pci_config_addr_t pci_addr = { .raw = 0 };
|
||||
|
||||
/* PCI address from section 15.4 of Intel Quark SoC X1000 Datasheet. */
|
||||
|
||||
pci_addr.dev = 20;
|
||||
pci_addr.func = 6;
|
||||
|
||||
/* Activate MMIO and DMA access. */
|
||||
pci_command_enable(pci_addr, PCI_CMD_2_BUS_MST_EN | PCI_CMD_1_MEM_SPACE_EN);
|
||||
|
||||
printf(LOG_PFX "Activated MMIO and DMA access.\n");
|
||||
|
||||
pci_addr.reg_off = PCI_CONFIG_REG_BAR0;
|
||||
|
||||
PROT_DOMAINS_INIT_ID(drv);
|
||||
/* Configure the device MMIO range and initialize the driver structure. */
|
||||
pci_init(&drv, pci_addr, MMIO_SZ,
|
||||
(uintptr_t)&meta, sizeof(quarkX1000_eth_meta_t));
|
||||
SYSCALLS_INIT(quarkX1000_eth_setup);
|
||||
SYSCALLS_AUTHZ(quarkX1000_eth_setup, drv);
|
||||
SYSCALLS_INIT(quarkX1000_eth_poll);
|
||||
SYSCALLS_AUTHZ(quarkX1000_eth_poll, drv);
|
||||
SYSCALLS_INIT(quarkX1000_eth_send);
|
||||
SYSCALLS_AUTHZ(quarkX1000_eth_send, drv);
|
||||
|
||||
quarkX1000_eth_setup(prot_domains_lookup_meta_phys_base(&drv));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_QUARKX1000_ETH_H_
|
||||
#define CPU_X86_DRIVERS_QUARKX1000_ETH_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void quarkX1000_eth_init(void);
|
||||
void quarkX1000_eth_poll(uint16_t *frame_len);
|
||||
void quarkX1000_eth_send(void);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_QUARKX1000_ETH_H_ */
|
|
@ -1,292 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gpio.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "helpers.h"
|
||||
#include "paging.h"
|
||||
#include "shared-isr.h"
|
||||
#include "syscalls.h"
|
||||
|
||||
/* GPIO Controler Registers */
|
||||
#define SWPORTA_DR 0x00
|
||||
#define SWPORTA_DDR 0x04
|
||||
#define INTEN 0x30
|
||||
#define INTMASK 0x34
|
||||
#define INTTYPE_LEVEL 0x38
|
||||
#define INT_POLARITY 0x3c
|
||||
#define INTSTATUS 0x40
|
||||
#define RAW_INTSTATUS 0x44
|
||||
#define DEBOUNCE 0x48
|
||||
#define PORTA_EOI 0x4c
|
||||
#define EXT_PORTA 0x50
|
||||
#define LS_SYNC 0x60
|
||||
|
||||
#define PINS 8
|
||||
|
||||
#define GPIO_IRQ 9
|
||||
|
||||
#define HIGHEST_REG LS_SYNC
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
|
||||
#define MMIO_SZ MIN_PAGE_SIZE
|
||||
#else
|
||||
#define MMIO_SZ (HIGHEST_REG + 4)
|
||||
#endif
|
||||
|
||||
PROT_DOMAINS_ALLOC(pci_driver_t, drv);
|
||||
|
||||
struct gpio_internal_data {
|
||||
quarkX1000_gpio_callback callback;
|
||||
};
|
||||
|
||||
static struct gpio_internal_data data;
|
||||
|
||||
void quarkX1000_gpio_mmin(uint32_t offset, uint32_t *res);
|
||||
SYSCALLS_DEFINE_SINGLETON(quarkX1000_gpio_mmin, drv,
|
||||
uint32_t offset, uint32_t *res)
|
||||
{
|
||||
uint32_t *loc_res;
|
||||
|
||||
PROT_DOMAINS_VALIDATE_PTR(loc_res, res, sizeof(*res));
|
||||
if(HIGHEST_REG < offset) {
|
||||
halt();
|
||||
}
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
PCI_MMIO_READL(drv, *loc_res, offset);
|
||||
prot_domains_disable_mmio();
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
read(uint32_t offset)
|
||||
{
|
||||
uint32_t res;
|
||||
quarkX1000_gpio_mmin(offset, &res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void quarkX1000_gpio_mmout(uint32_t offset, uint32_t val);
|
||||
SYSCALLS_DEFINE_SINGLETON(quarkX1000_gpio_mmout, drv,
|
||||
uint32_t offset, uint32_t val)
|
||||
{
|
||||
if(HIGHEST_REG < offset) {
|
||||
halt();
|
||||
}
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
PCI_MMIO_WRITEL(drv, offset, val);
|
||||
prot_domains_disable_mmio();
|
||||
}
|
||||
|
||||
static inline void
|
||||
write(uint32_t offset, uint32_t val)
|
||||
{
|
||||
quarkX1000_gpio_mmout(offset, val);
|
||||
}
|
||||
|
||||
/* value must be 0x0 or 0x1 */
|
||||
static void
|
||||
set_bit(uint32_t offset, uint32_t bit, uint32_t value)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
reg = read(offset);
|
||||
|
||||
reg &= ~BIT(bit);
|
||||
reg |= value << bit;
|
||||
|
||||
write(offset, reg);
|
||||
}
|
||||
|
||||
static bool
|
||||
gpio_isr(void)
|
||||
{
|
||||
uint32_t int_status;
|
||||
|
||||
int_status = read(INTSTATUS);
|
||||
|
||||
if(int_status == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (data.callback)
|
||||
data.callback(int_status);
|
||||
|
||||
write(PORTA_EOI, -1);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
gpio_interrupt_config(uint8_t pin, int flags)
|
||||
{
|
||||
/* set as input */
|
||||
set_bit(SWPORTA_DDR, pin, 0);
|
||||
|
||||
/* set interrupt enabled */
|
||||
set_bit(INTEN, pin, 1);
|
||||
|
||||
/* unmask interrupt */
|
||||
set_bit(INTMASK, pin, 0);
|
||||
|
||||
/* set active high/low */
|
||||
set_bit(INT_POLARITY, pin, !!(flags & QUARKX1000_GPIO_ACTIVE_HIGH));
|
||||
|
||||
/* set level/edge */
|
||||
set_bit(INTTYPE_LEVEL, pin, !!(flags & QUARKX1000_GPIO_EDGE));
|
||||
|
||||
/* set debounce */
|
||||
set_bit(DEBOUNCE, pin, !!(flags & QUARKX1000_GPIO_DEBOUNCE));
|
||||
|
||||
/* set clock synchronous */
|
||||
set_bit(LS_SYNC, 0, !!(flags & QUARKX1000_GPIO_CLOCK_SYNC));
|
||||
}
|
||||
|
||||
int
|
||||
quarkX1000_gpio_config(uint8_t pin, int flags)
|
||||
{
|
||||
if (((flags & QUARKX1000_GPIO_IN) && (flags & QUARKX1000_GPIO_OUT)) ||
|
||||
((flags & QUARKX1000_GPIO_INT) && (flags & QUARKX1000_GPIO_OUT))) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (flags & QUARKX1000_GPIO_INT) {
|
||||
gpio_interrupt_config(pin, flags);
|
||||
} else {
|
||||
/* set direction */
|
||||
set_bit(SWPORTA_DDR, pin, !!(flags & QUARKX1000_GPIO_OUT));
|
||||
|
||||
/* set interrupt disabled */
|
||||
set_bit(INTEN, pin, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
quarkX1000_gpio_config_port(int flags)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < PINS; i++) {
|
||||
if (quarkX1000_gpio_config(i, flags) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
quarkX1000_gpio_read(uint8_t pin, uint8_t *value)
|
||||
{
|
||||
uint32_t value32 = read(EXT_PORTA);
|
||||
*value = !!(value32 & BIT(pin));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
quarkX1000_gpio_write(uint8_t pin, uint8_t value)
|
||||
{
|
||||
set_bit(SWPORTA_DR, pin, !!value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
quarkX1000_gpio_read_port(uint8_t *value)
|
||||
{
|
||||
uint32_t value32 = read(EXT_PORTA);
|
||||
*value = value32 & ~0xFFFFFF00;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
quarkX1000_gpio_write_port(uint8_t value)
|
||||
{
|
||||
write(SWPORTA_DR, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
quarkX1000_gpio_set_callback(quarkX1000_gpio_callback callback)
|
||||
{
|
||||
data.callback = callback;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
quarkX1000_gpio_clock_enable(void)
|
||||
{
|
||||
set_bit(LS_SYNC, 0, 1);
|
||||
}
|
||||
|
||||
void
|
||||
quarkX1000_gpio_clock_disable(void)
|
||||
{
|
||||
set_bit(LS_SYNC, 0, 0);
|
||||
}
|
||||
|
||||
DEFINE_SHARED_IRQ(GPIO_IRQ, IRQAGENT3, INTC, PIRQC, gpio_isr);
|
||||
|
||||
int
|
||||
quarkX1000_gpio_init(void)
|
||||
{
|
||||
pci_config_addr_t pci_addr;
|
||||
|
||||
pci_addr.raw = 0;
|
||||
pci_addr.bus = 0;
|
||||
pci_addr.dev = 21;
|
||||
pci_addr.func = 2;
|
||||
pci_addr.reg_off = PCI_CONFIG_REG_BAR1;
|
||||
|
||||
pci_command_enable(pci_addr, PCI_CMD_1_MEM_SPACE_EN);
|
||||
|
||||
PROT_DOMAINS_INIT_ID(drv);
|
||||
pci_init(&drv, pci_addr, MMIO_SZ, 0, 0);
|
||||
SYSCALLS_INIT(quarkX1000_gpio_mmin);
|
||||
SYSCALLS_AUTHZ(quarkX1000_gpio_mmin, drv);
|
||||
SYSCALLS_INIT(quarkX1000_gpio_mmout);
|
||||
SYSCALLS_AUTHZ(quarkX1000_gpio_mmout, drv);
|
||||
|
||||
data.callback = 0;
|
||||
|
||||
quarkX1000_gpio_clock_enable();
|
||||
|
||||
/* clear registers */
|
||||
write(INTEN, 0);
|
||||
write(INTMASK, 0);
|
||||
write(PORTA_EOI, 0);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_QUARKX1000_GPIO_H_
|
||||
#define CPU_X86_DRIVERS_QUARKX1000_GPIO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
#define QUARKX1000_GPIO_IN (0 << 0)
|
||||
#define QUARKX1000_GPIO_OUT (1 << 0)
|
||||
#define QUARKX1000_GPIO_INT (1 << 1)
|
||||
#define QUARKX1000_GPIO_ACTIVE_LOW (0 << 2)
|
||||
#define QUARKX1000_GPIO_ACTIVE_HIGH (1 << 2)
|
||||
#define QUARKX1000_GPIO_LEVEL (0 << 3)
|
||||
#define QUARKX1000_GPIO_EDGE (1 << 3)
|
||||
#define QUARKX1000_GPIO_DEBOUNCE (1 << 4)
|
||||
#define QUARKX1000_GPIO_CLOCK_SYNC (1 << 5)
|
||||
#define QUARKX1000_GPIO_POL_NORMAL (0 << 6)
|
||||
#define QUARKX1000_GPIO_POL_INV (1 << 6)
|
||||
#define QUARKX1000_GPIO_PUD_NORMAL (0 << 7)
|
||||
#define QUARKX1000_GPIO_PUD_PULL_UP (1 << 7)
|
||||
#define QUARKX1000_GPIO_PUD_PULL_DOWN (2 << 7)
|
||||
|
||||
#define QUARKX1000_GPIO_DIR_MASK (1 << 0)
|
||||
#define QUARKX1000_GPIO_POL_MASK (1 << 6)
|
||||
#define QUARKX1000_GPIO_PUD_MASK (3 << 7)
|
||||
|
||||
typedef void (*quarkX1000_gpio_callback)(uint32_t);
|
||||
|
||||
int quarkX1000_gpio_init(void);
|
||||
|
||||
int quarkX1000_gpio_config(uint8_t pin, int flags);
|
||||
int quarkX1000_gpio_read(uint8_t pin, uint8_t *value);
|
||||
int quarkX1000_gpio_write(uint8_t pin, uint8_t value);
|
||||
|
||||
int quarkX1000_gpio_config_port(int flags);
|
||||
int quarkX1000_gpio_read_port(uint8_t *value);
|
||||
int quarkX1000_gpio_write_port(uint8_t value);
|
||||
|
||||
int quarkX1000_gpio_set_callback(quarkX1000_gpio_callback callback);
|
||||
|
||||
void quarkX1000_gpio_clock_enable(void);
|
||||
void quarkX1000_gpio_clock_disable(void);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_QUARKX1000_GPIO_H_ */
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_QUARKX1000_I2C_REGISTERS_H_
|
||||
#define CPU_X86_DRIVERS_QUARKX1000_I2C_REGISTERS_H_
|
||||
|
||||
#define QUARKX1000_IC_CON 0x00
|
||||
#define QUARKX1000_IC_TAR 0x04
|
||||
#define QUARKX1000_IC_DATA_CMD 0x10
|
||||
#define QUARKX1000_IC_SS_SCL_HCNT 0x14
|
||||
#define QUARKX1000_IC_SS_SCL_LCNT 0x18
|
||||
#define QUARKX1000_IC_FS_SCL_HCNT 0x1C
|
||||
#define QUARKX1000_IC_FS_SCL_LCNT 0x20
|
||||
#define QUARKX1000_IC_INTR_STAT 0x2C
|
||||
#define QUARKX1000_IC_INTR_MASK 0x30
|
||||
#define QUARKX1000_IC_RAW_INTR_STAT 0x34
|
||||
#define QUARKX1000_IC_RX_TL 0x38
|
||||
#define QUARKX1000_IC_TX_TL 0x3C
|
||||
#define QUARKX1000_IC_CLR_INTR 0x40
|
||||
#define QUARKX1000_IC_CLR_RX_UNDER 0x44
|
||||
#define QUARKX1000_IC_CLR_RX_OVER 0x48
|
||||
#define QUARKX1000_IC_CLR_TX_OVER 0x4C
|
||||
#define QUARKX1000_IC_CLR_RD_REQ 0x50
|
||||
#define QUARKX1000_IC_CLR_TX_ABRT 0x54
|
||||
#define QUARKX1000_IC_CLR_ACTIVITY 0x5C
|
||||
#define QUARKX1000_IC_CLR_STOP_DET 0x60
|
||||
#define QUARKX1000_IC_CLR_START_DET 0x64
|
||||
#define QUARKX1000_IC_ENABLE 0x6C
|
||||
#define QUARKX1000_IC_STATUS 0x70
|
||||
#define QUARKX1000_IC_TXFLR 0x74
|
||||
#define QUARKX1000_IC_RXFLR 0x78
|
||||
#define QUARKX1000_IC_SDA_HOLD 0x7C
|
||||
#define QUARKX1000_IC_TX_ABRT_SOURCE 0x80
|
||||
#define QUARKX1000_IC_ENABLE_STATUS 0x9C
|
||||
#define QUARKX1000_IC_FS_SPKLEN 0xA0
|
||||
|
||||
#define QUARKX1000_IC_HIGHEST QUARKX1000_IC_FS_SPKLEN
|
||||
|
||||
/* IC_CON */
|
||||
#define QUARKX1000_IC_CON_MASTER_MODE_SHIFT 0
|
||||
#define QUARKX1000_IC_CON_MASTER_MODE_MASK 0x01
|
||||
#define QUARKX1000_IC_CON_SPEED_SHIFT 1
|
||||
#define QUARKX1000_IC_CON_SPEED_MASK 0x06
|
||||
#define QUARKX1000_IC_CON_10BITADDR_MASTER_SHIFT 4
|
||||
#define QUARKX1000_IC_CON_10BITADDR_MASTER_MASK 0x10
|
||||
#define QUARKX1000_IC_CON_RESTART_EN_SHIFT 5
|
||||
#define QUARKX1000_IC_CON_RESTART_EN_MASK 0x20
|
||||
|
||||
/* IC_TAR */
|
||||
#define QUARKX1000_IC_TAR_SHIFT 0
|
||||
#define QUARKX1000_IC_TAR_MASK 0x3FF
|
||||
|
||||
/* IC_DATA_CMD */
|
||||
#define QUARKX1000_IC_DATA_CMD_DAT_SHIFT 0
|
||||
#define QUARKX1000_IC_DATA_CMD_DAT_MASK 0x0FF
|
||||
#define QUARKX1000_IC_DATA_CMD_CMD_SHIFT 8
|
||||
#define QUARKX1000_IC_DATA_CMD_CMD_MASK 0x100
|
||||
#define QUARKX1000_IC_DATA_CMD_STOP_SHIFT 9
|
||||
#define QUARKX1000_IC_DATA_CMD_STOP_MASK 0x200
|
||||
#define QUARKX1000_IC_DATA_CMD_RESTART_SHIFT 10
|
||||
#define QUARKX1000_IC_DATA_CMD_RESTART_MASK 0x400
|
||||
|
||||
/* IC_SS_SCL_HCNT */
|
||||
#define QUARKX1000_IC_SS_SCL_HCNT_SHIFT 0
|
||||
#define QUARKX1000_IC_SS_SCL_HCNT_MASK 0xFFFF
|
||||
|
||||
/* IC_SS_SCL_LCNT */
|
||||
#define QUARKX1000_IC_SS_SCL_LCNT_SHIFT 0
|
||||
#define QUARKX1000_IC_SS_SCL_LCNT_MASK 0xFFFF
|
||||
|
||||
/* IC_FS_SCL_HCNT */
|
||||
#define QUARKX1000_IC_FS_SCL_HCNT_SHIFT 0
|
||||
#define QUARKX1000_IC_FS_SCL_HCNT_MASK 0xFFFF
|
||||
|
||||
/* IC_FS_SCL_LCNT */
|
||||
#define QUARKX1000_IC_FS_SCL_LCNT_SHIFT 0
|
||||
#define QUARKX1000_IC_FS_SCL_LCNT_MASK 0xFFFF
|
||||
|
||||
/* IC_INTR_STAT */
|
||||
#define QUARKX1000_IC_INTR_STAT_RX_UNDER_SHIFT 0
|
||||
#define QUARKX1000_IC_INTR_STAT_RX_UNDER_MASK 0x001
|
||||
#define QUARKX1000_IC_INTR_STAT_RX_OVER_SHIFT 1
|
||||
#define QUARKX1000_IC_INTR_STAT_RX_OVER_MASK 0x002
|
||||
#define QUARKX1000_IC_INTR_STAT_RX_FULL_SHIFT 2
|
||||
#define QUARKX1000_IC_INTR_STAT_RX_FULL_MASK 0x004
|
||||
#define QUARKX1000_IC_INTR_STAT_TX_OVER_SHIFT 3
|
||||
#define QUARKX1000_IC_INTR_STAT_TX_OVER_MASK 0x008
|
||||
#define QUARKX1000_IC_INTR_STAT_TX_EMPTY_SHIFT 4
|
||||
#define QUARKX1000_IC_INTR_STAT_TX_EMPTY_MASK 0x010
|
||||
#define QUARKX1000_IC_INTR_STAT_RD_REQ_SHIFT 5
|
||||
#define QUARKX1000_IC_INTR_STAT_RD_REQ_MASK 0x020
|
||||
#define QUARKX1000_IC_INTR_STAT_TX_ABRT_SHIFT 6
|
||||
#define QUARKX1000_IC_INTR_STAT_TX_ABRT_MASK 0x040
|
||||
#define QUARKX1000_IC_INTR_STAT_ACTIVITY_SHIFT 8
|
||||
#define QUARKX1000_IC_INTR_STAT_ACTIVITY_MASK 0x100
|
||||
#define QUARKX1000_IC_INTR_STAT_STOP_DET_SHIFT 9
|
||||
#define QUARKX1000_IC_INTR_STAT_STOP_DET_MASK 0x200
|
||||
#define QUARKX1000_IC_INTR_STAT_START_DET_SHIFT 10
|
||||
#define QUARKX1000_IC_INTR_STAT_START_DET_MASK 0x400
|
||||
|
||||
/* IC_ENABLE */
|
||||
#define QUARKX1000_IC_ENABLE_SHIFT 0
|
||||
#define QUARKX1000_IC_ENABLE_MASK 0x01
|
||||
|
||||
/* IC_STATUS */
|
||||
#define QUARKX1000_IC_STATUS_ACTIVITY_SHIFT 0
|
||||
#define QUARKX1000_IC_STATUS_ACTIVITY_MASK 0x01
|
||||
#define QUARKX1000_IC_STATUS_TFNF_SHIFT 1
|
||||
#define QUARKX1000_IC_STATUS_TFNF_MASK 0x02
|
||||
#define QUARKX1000_IC_STATUS_TFE_SHIFT 2
|
||||
#define QUARKX1000_IC_STATUS_TFE_MASK 0x04
|
||||
#define QUARKX1000_IC_STATUS_RFNE_SHIFT 3
|
||||
#define QUARKX1000_IC_STATUS_RFNE_MASK 0x08
|
||||
#define QUARKX1000_IC_STATUS_RFF_SHIFT 4
|
||||
#define QUARKX1000_IC_STATUS_RFF_MASK 0x10
|
||||
#define QUARKX1000_IC_STATUS_MST_ACTIVITY_SHIFT 5
|
||||
#define QUARKX1000_IC_STATUS_MST_ACTIVITY_MASK 0x20
|
||||
|
||||
/* IC_TXFLR */
|
||||
#define QUARKX1000_IC_TXFLR_SHIFT 0
|
||||
#define QUARKX1000_IC_TXFLR_MASK 0x1F
|
||||
|
||||
/* IC_RXFLR */
|
||||
#define QUARKX1000_IC_RXFLR_SHIFT 0
|
||||
#define QUARKX1000_IC_RXFLR_MASK 0x1F
|
||||
|
||||
/* IC_FS_SPKLEN */
|
||||
#define QUARKX1000_IC_FS_SPKLEN_SHIFT 0
|
||||
#define QUARKX1000_IC_FS_SPKLEN_MASK 0xFF
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_QUARKX1000_I2C_REGISTERS_H_ */
|
|
@ -1,575 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "i2c.h"
|
||||
|
||||
#include "i2c-registers.h"
|
||||
#include "paging.h"
|
||||
#include "shared-isr.h"
|
||||
#include "syscalls.h"
|
||||
|
||||
#define I2C_CLOCK_SPEED 25 /* kHz */
|
||||
#define I2C_FIFO_DEPTH 16
|
||||
|
||||
#define I2C_STD_HCNT (I2C_CLOCK_SPEED * 4)
|
||||
#define I2C_STD_LCNT (I2C_CLOCK_SPEED * 5)
|
||||
#define I2C_FS_HCNT (I2C_CLOCK_SPEED)
|
||||
#define I2C_FS_LCNT (I2C_CLOCK_SPEED)
|
||||
|
||||
#define I2C_FS_SPKLEN_LCNT_OFFSET 8
|
||||
#define I2C_FS_SPKLEN_HCNT_OFFSET 6
|
||||
|
||||
#define I2C_POLLING_TIMEOUT (CLOCK_SECOND / 10)
|
||||
|
||||
#define I2C_IRQ 9
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
|
||||
#define MMIO_SZ MIN_PAGE_SIZE
|
||||
#else
|
||||
#define MMIO_SZ (QUARKX1000_IC_HIGHEST + 4)
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
I2C_DIRECTION_READ,
|
||||
I2C_DIRECTION_WRITE
|
||||
} I2C_DIRECTION;
|
||||
|
||||
PROT_DOMAINS_ALLOC(pci_driver_t, drv);
|
||||
|
||||
struct quarkX1000_i2c_config {
|
||||
QUARKX1000_I2C_SPEED speed;
|
||||
QUARKX1000_I2C_ADDR_MODE addressing_mode;
|
||||
|
||||
quarkX1000_i2c_callback cb_rx;
|
||||
quarkX1000_i2c_callback cb_tx;
|
||||
quarkX1000_i2c_callback cb_err;
|
||||
};
|
||||
|
||||
struct i2c_internal_data {
|
||||
struct quarkX1000_i2c_config config;
|
||||
|
||||
I2C_DIRECTION direction;
|
||||
|
||||
uint8_t rx_len;
|
||||
uint8_t *rx_buffer;
|
||||
uint8_t tx_len;
|
||||
uint8_t *tx_buffer;
|
||||
uint8_t rx_tx_len;
|
||||
|
||||
uint32_t hcnt;
|
||||
uint32_t lcnt;
|
||||
};
|
||||
|
||||
static struct i2c_internal_data device;
|
||||
|
||||
static int inited = 0;
|
||||
|
||||
void quarkX1000_i2c_mmin(uint32_t offset, uint32_t *res);
|
||||
SYSCALLS_DEFINE_SINGLETON(quarkX1000_i2c_mmin, drv,
|
||||
uint32_t offset, uint32_t *res)
|
||||
{
|
||||
uint32_t *loc_res;
|
||||
|
||||
PROT_DOMAINS_VALIDATE_PTR(loc_res, res, sizeof(*res));
|
||||
if(QUARKX1000_IC_HIGHEST < offset) {
|
||||
halt();
|
||||
}
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
PCI_MMIO_READL(drv, *loc_res, offset);
|
||||
prot_domains_disable_mmio();
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
read(uint32_t offset)
|
||||
{
|
||||
uint32_t res;
|
||||
quarkX1000_i2c_mmin(offset, &res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
void quarkX1000_i2c_mmout(uint32_t offset, uint32_t val);
|
||||
SYSCALLS_DEFINE_SINGLETON(quarkX1000_i2c_mmout, drv,
|
||||
uint32_t offset, uint32_t val)
|
||||
{
|
||||
if(QUARKX1000_IC_HIGHEST < offset) {
|
||||
halt();
|
||||
}
|
||||
|
||||
prot_domains_enable_mmio();
|
||||
PCI_MMIO_WRITEL(drv, offset, val);
|
||||
prot_domains_disable_mmio();
|
||||
}
|
||||
|
||||
static inline void
|
||||
write(uint32_t offset, uint32_t val)
|
||||
{
|
||||
quarkX1000_i2c_mmout(offset, val);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_value(uint32_t offset, uint32_t mask, uint32_t shift)
|
||||
{
|
||||
uint32_t register_value = read(offset);
|
||||
|
||||
register_value &= ~(0xFFFFFFFF - mask);
|
||||
|
||||
return register_value >> shift;
|
||||
}
|
||||
|
||||
static void
|
||||
set_value(uint32_t offset, uint32_t mask, uint32_t shift, uint32_t value)
|
||||
{
|
||||
uint32_t register_value = read(offset);
|
||||
|
||||
register_value &= ~mask;
|
||||
register_value |= value << shift;
|
||||
|
||||
write(offset, register_value);
|
||||
}
|
||||
|
||||
static void
|
||||
i2c_data_read(void)
|
||||
{
|
||||
uint8_t i, rx_cnt;
|
||||
|
||||
if (device.rx_len == 0)
|
||||
return;
|
||||
|
||||
rx_cnt = get_value(QUARKX1000_IC_RXFLR,
|
||||
QUARKX1000_IC_RXFLR_MASK, QUARKX1000_IC_RXFLR_SHIFT);
|
||||
|
||||
if (rx_cnt > device.rx_len)
|
||||
rx_cnt = device.rx_len;
|
||||
|
||||
for (i = 0; i < rx_cnt; i++) {
|
||||
device.rx_buffer[i] = get_value(QUARKX1000_IC_DATA_CMD,
|
||||
QUARKX1000_IC_DATA_CMD_DAT_MASK, QUARKX1000_IC_DATA_CMD_DAT_SHIFT);
|
||||
}
|
||||
|
||||
device.rx_buffer += i;
|
||||
device.rx_len -= i;
|
||||
}
|
||||
|
||||
static void
|
||||
i2c_data_send(void)
|
||||
{
|
||||
uint32_t data = 0;
|
||||
uint8_t i, tx_cnt;
|
||||
|
||||
if (device.rx_tx_len == 0)
|
||||
return;
|
||||
|
||||
tx_cnt = I2C_FIFO_DEPTH - get_value(QUARKX1000_IC_TXFLR,
|
||||
QUARKX1000_IC_TXFLR_MASK, QUARKX1000_IC_TXFLR_SHIFT);
|
||||
|
||||
if (tx_cnt > device.rx_tx_len)
|
||||
tx_cnt = device.rx_tx_len;
|
||||
|
||||
for (i = 0; i < tx_cnt; i++) {
|
||||
if (device.tx_len > 0) {
|
||||
data = device.tx_buffer[i];
|
||||
|
||||
if (device.tx_len == 1)
|
||||
data |= (device.rx_len > 0) ? QUARKX1000_IC_DATA_CMD_RESTART_MASK : QUARKX1000_IC_DATA_CMD_STOP_MASK;
|
||||
|
||||
device.tx_len -= 1;
|
||||
} else {
|
||||
data = QUARKX1000_IC_DATA_CMD_CMD_MASK;
|
||||
|
||||
if (device.rx_tx_len == 1)
|
||||
data |= QUARKX1000_IC_DATA_CMD_STOP_MASK;
|
||||
}
|
||||
|
||||
write(QUARKX1000_IC_DATA_CMD, data);
|
||||
device.rx_tx_len -= 1;
|
||||
}
|
||||
|
||||
device.tx_buffer += i;
|
||||
}
|
||||
|
||||
static bool
|
||||
i2c_isr(void)
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
if (read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_STOP_DET_MASK) {
|
||||
i2c_data_read();
|
||||
|
||||
write(QUARKX1000_IC_INTR_MASK, 0);
|
||||
read(QUARKX1000_IC_CLR_INTR);
|
||||
|
||||
if (device.direction == I2C_DIRECTION_WRITE) {
|
||||
if (device.config.cb_tx)
|
||||
device.config.cb_tx();
|
||||
} else {
|
||||
if (device.config.cb_rx)
|
||||
device.config.cb_rx();
|
||||
}
|
||||
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_TX_EMPTY_MASK) {
|
||||
i2c_data_send();
|
||||
if (device.rx_tx_len <= 0) {
|
||||
set_value(QUARKX1000_IC_INTR_MASK,
|
||||
QUARKX1000_IC_INTR_STAT_TX_EMPTY_MASK, QUARKX1000_IC_INTR_STAT_TX_EMPTY_SHIFT, 0);
|
||||
set_value(QUARKX1000_IC_INTR_MASK,
|
||||
QUARKX1000_IC_INTR_STAT_STOP_DET_MASK, QUARKX1000_IC_INTR_STAT_STOP_DET_SHIFT, 1);
|
||||
}
|
||||
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if(read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_RX_FULL_MASK) {
|
||||
i2c_data_read();
|
||||
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (read(QUARKX1000_IC_INTR_STAT) & (QUARKX1000_IC_INTR_STAT_TX_ABRT_MASK
|
||||
| QUARKX1000_IC_INTR_STAT_TX_OVER_MASK | QUARKX1000_IC_INTR_STAT_RX_OVER_MASK
|
||||
| QUARKX1000_IC_INTR_STAT_RX_UNDER_MASK)) {
|
||||
write(QUARKX1000_IC_INTR_MASK, 0);
|
||||
read(QUARKX1000_IC_CLR_INTR);
|
||||
|
||||
if (device.config.cb_err)
|
||||
device.config.cb_err();
|
||||
|
||||
handled = true;
|
||||
}
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
void
|
||||
quarkX1000_i2c_configure(QUARKX1000_I2C_SPEED speed,
|
||||
QUARKX1000_I2C_ADDR_MODE addressing_mode)
|
||||
{
|
||||
uint32_t hcnt, lcnt;
|
||||
uint8_t ic_fs_spklen;
|
||||
|
||||
device.config.speed = speed;
|
||||
device.config.addressing_mode = addressing_mode;
|
||||
|
||||
if (device.config.speed == QUARKX1000_I2C_SPEED_STANDARD) {
|
||||
lcnt = I2C_STD_LCNT;
|
||||
hcnt = I2C_STD_HCNT;
|
||||
} else {
|
||||
lcnt = I2C_FS_LCNT;
|
||||
hcnt = I2C_FS_HCNT;
|
||||
}
|
||||
|
||||
ic_fs_spklen = get_value(QUARKX1000_IC_FS_SPKLEN,
|
||||
QUARKX1000_IC_FS_SPKLEN_MASK, QUARKX1000_IC_FS_SPKLEN_SHIFT);
|
||||
|
||||
/* We adjust the Low Count and High Count based on the Spike Suppression Limit */
|
||||
device.lcnt = (lcnt < (ic_fs_spklen + I2C_FS_SPKLEN_LCNT_OFFSET)) ? ic_fs_spklen + I2C_FS_SPKLEN_LCNT_OFFSET : lcnt;
|
||||
device.hcnt = (hcnt < (ic_fs_spklen + I2C_FS_SPKLEN_HCNT_OFFSET)) ? ic_fs_spklen + I2C_FS_SPKLEN_HCNT_OFFSET : hcnt;
|
||||
|
||||
/* Clear interrupts. */
|
||||
read(QUARKX1000_IC_CLR_INTR);
|
||||
}
|
||||
|
||||
void
|
||||
quarkX1000_i2c_set_callbacks(quarkX1000_i2c_callback rx,
|
||||
quarkX1000_i2c_callback tx,
|
||||
quarkX1000_i2c_callback err)
|
||||
{
|
||||
device.config.cb_rx = rx;
|
||||
device.config.cb_tx = tx;
|
||||
device.config.cb_err = err;
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_setup(void)
|
||||
{
|
||||
/* Clear all values */
|
||||
write(QUARKX1000_IC_CON, 0);
|
||||
|
||||
/* Clear interrupts */
|
||||
read(QUARKX1000_IC_CLR_INTR);
|
||||
|
||||
/* Quark X1000 SoC I2C only supports master mode. */
|
||||
set_value(QUARKX1000_IC_CON,
|
||||
QUARKX1000_IC_CON_MASTER_MODE_MASK, QUARKX1000_IC_CON_MASTER_MODE_SHIFT, 1);
|
||||
|
||||
/* Set restart enable */
|
||||
set_value(QUARKX1000_IC_CON,
|
||||
QUARKX1000_IC_CON_RESTART_EN_MASK, QUARKX1000_IC_CON_RESTART_EN_SHIFT, 1);
|
||||
|
||||
/* Set addressing mode */
|
||||
if (device.config.addressing_mode == QUARKX1000_I2C_ADDR_MODE_10BIT) {
|
||||
set_value(QUARKX1000_IC_CON,
|
||||
QUARKX1000_IC_CON_10BITADDR_MASTER_MASK, QUARKX1000_IC_CON_10BITADDR_MASTER_SHIFT, 1);
|
||||
}
|
||||
|
||||
if (device.config.speed == QUARKX1000_I2C_SPEED_STANDARD) {
|
||||
set_value(QUARKX1000_IC_SS_SCL_LCNT,
|
||||
QUARKX1000_IC_SS_SCL_LCNT_MASK, QUARKX1000_IC_SS_SCL_LCNT_SHIFT, device.lcnt);
|
||||
set_value(QUARKX1000_IC_SS_SCL_HCNT,
|
||||
QUARKX1000_IC_SS_SCL_HCNT_MASK, QUARKX1000_IC_SS_SCL_HCNT_SHIFT, device.hcnt);
|
||||
set_value(QUARKX1000_IC_CON,
|
||||
QUARKX1000_IC_CON_SPEED_MASK, QUARKX1000_IC_CON_SPEED_SHIFT, 0x1);
|
||||
} else {
|
||||
set_value(QUARKX1000_IC_FS_SCL_LCNT,
|
||||
QUARKX1000_IC_FS_SCL_LCNT_MASK, QUARKX1000_IC_FS_SCL_LCNT_SHIFT, device.lcnt);
|
||||
set_value(QUARKX1000_IC_FS_SCL_HCNT,
|
||||
QUARKX1000_IC_FS_SCL_HCNT_MASK, QUARKX1000_IC_FS_SCL_HCNT_SHIFT, device.hcnt);
|
||||
set_value(QUARKX1000_IC_CON,
|
||||
QUARKX1000_IC_CON_SPEED_MASK, QUARKX1000_IC_CON_SPEED_SHIFT, 0x2);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
i2c_operation_setup(uint8_t *write_buf, uint8_t write_len,
|
||||
uint8_t *read_buf, uint8_t read_len, uint16_t addr)
|
||||
{
|
||||
device.rx_len = read_len;
|
||||
device.rx_buffer = read_buf;
|
||||
device.tx_len = write_len;
|
||||
device.tx_buffer = write_buf;
|
||||
device.rx_tx_len = device.rx_len + device.tx_len;
|
||||
|
||||
/* Disable controller */
|
||||
set_value(QUARKX1000_IC_ENABLE,
|
||||
QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
|
||||
|
||||
i2c_setup();
|
||||
|
||||
/* Disable interrupts */
|
||||
write(QUARKX1000_IC_INTR_MASK, 0);
|
||||
|
||||
/* Clear interrupts */
|
||||
read(QUARKX1000_IC_CLR_INTR);
|
||||
|
||||
/* Set address of target slave */
|
||||
set_value(QUARKX1000_IC_TAR,
|
||||
QUARKX1000_IC_TAR_MASK, QUARKX1000_IC_TAR_SHIFT, addr);
|
||||
}
|
||||
|
||||
/* This is an interrupt based operation */
|
||||
static int
|
||||
i2c_operation(uint8_t *write_buf, uint8_t write_len,
|
||||
uint8_t *read_buf, uint8_t read_len, uint16_t addr)
|
||||
{
|
||||
if (read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_ACTIVITY_MASK)
|
||||
return -1;
|
||||
|
||||
i2c_operation_setup(write_buf, write_len, read_buf, read_len, addr);
|
||||
|
||||
/* Enable master TX and RX interrupts */
|
||||
set_value(QUARKX1000_IC_INTR_MASK,
|
||||
QUARKX1000_IC_INTR_STAT_TX_OVER_MASK, QUARKX1000_IC_INTR_STAT_TX_OVER_SHIFT, 1);
|
||||
set_value(QUARKX1000_IC_INTR_MASK,
|
||||
QUARKX1000_IC_INTR_STAT_TX_EMPTY_MASK, QUARKX1000_IC_INTR_STAT_TX_EMPTY_SHIFT, 1);
|
||||
set_value(QUARKX1000_IC_INTR_MASK,
|
||||
QUARKX1000_IC_INTR_STAT_TX_ABRT_MASK, QUARKX1000_IC_INTR_STAT_TX_ABRT_SHIFT, 1);
|
||||
set_value(QUARKX1000_IC_INTR_MASK,
|
||||
QUARKX1000_IC_INTR_STAT_RX_UNDER_MASK, QUARKX1000_IC_INTR_STAT_RX_UNDER_SHIFT, 1);
|
||||
set_value(QUARKX1000_IC_INTR_MASK,
|
||||
QUARKX1000_IC_INTR_STAT_RX_OVER_MASK, QUARKX1000_IC_INTR_STAT_RX_OVER_SHIFT, 1);
|
||||
set_value(QUARKX1000_IC_INTR_MASK,
|
||||
QUARKX1000_IC_INTR_STAT_RX_FULL_MASK, QUARKX1000_IC_INTR_STAT_RX_FULL_SHIFT, 1);
|
||||
set_value(QUARKX1000_IC_INTR_MASK,
|
||||
QUARKX1000_IC_INTR_STAT_STOP_DET_MASK, QUARKX1000_IC_INTR_STAT_STOP_DET_SHIFT, 1);
|
||||
|
||||
/* Enable controller */
|
||||
set_value(QUARKX1000_IC_ENABLE,
|
||||
QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This is an interrupt based write */
|
||||
int
|
||||
quarkX1000_i2c_write(uint8_t *buf, uint8_t len, uint16_t addr)
|
||||
{
|
||||
device.direction = I2C_DIRECTION_WRITE;
|
||||
return i2c_operation(buf, len, 0, 0, addr);
|
||||
}
|
||||
|
||||
/* This is an interrupt based read */
|
||||
int
|
||||
quarkX1000_i2c_read(uint8_t *buf, uint8_t len, uint16_t addr)
|
||||
{
|
||||
device.direction = I2C_DIRECTION_READ;
|
||||
return i2c_operation(0, 0, buf, len, addr);
|
||||
}
|
||||
|
||||
static int
|
||||
i2c_polling_operation(uint8_t *write_buf, uint8_t write_len,
|
||||
uint8_t *read_buf, uint8_t read_len, uint16_t addr)
|
||||
{
|
||||
uint32_t start_time, intr_mask_stat;
|
||||
|
||||
if (!(read(QUARKX1000_IC_CON) & QUARKX1000_IC_CON_MASTER_MODE_MASK))
|
||||
return -1;
|
||||
|
||||
/* Wait i2c idle */
|
||||
start_time = clock_seconds();
|
||||
while (read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_ACTIVITY_MASK) {
|
||||
if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get interrupt mask to restore in the end of polling operation */
|
||||
intr_mask_stat = read(QUARKX1000_IC_INTR_MASK);
|
||||
|
||||
i2c_operation_setup(write_buf, write_len, read_buf, read_len, addr);
|
||||
|
||||
/* Enable controller */
|
||||
set_value(QUARKX1000_IC_ENABLE,
|
||||
QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 1);
|
||||
|
||||
/* Transmit */
|
||||
if (device.tx_len != 0) {
|
||||
while (device.tx_len > 0) {
|
||||
start_time = clock_seconds();
|
||||
while (!(read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_TFNF_MASK)) {
|
||||
if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
|
||||
set_value(QUARKX1000_IC_ENABLE,
|
||||
QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
i2c_data_send();
|
||||
}
|
||||
|
||||
start_time = clock_seconds();
|
||||
while (!(read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_TFE_MASK)) {
|
||||
if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
|
||||
set_value(QUARKX1000_IC_ENABLE,
|
||||
QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
i2c_data_send();
|
||||
|
||||
/* Receive */
|
||||
if (device.rx_len != 0) {
|
||||
while (device.rx_len > 0) {
|
||||
start_time = clock_seconds();
|
||||
while (!(read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_RFNE_MASK)) {
|
||||
if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
|
||||
set_value(QUARKX1000_IC_ENABLE,
|
||||
QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
i2c_data_read();
|
||||
}
|
||||
}
|
||||
|
||||
/* Stop Det */
|
||||
start_time = clock_seconds();
|
||||
while (!(read(QUARKX1000_IC_RAW_INTR_STAT) & QUARKX1000_IC_INTR_STAT_STOP_DET_MASK)) {
|
||||
if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
|
||||
set_value(QUARKX1000_IC_ENABLE,
|
||||
QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
read(QUARKX1000_IC_CLR_STOP_DET);
|
||||
|
||||
/* Wait i2c idle */
|
||||
start_time = clock_seconds();
|
||||
while (read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_ACTIVITY_MASK) {
|
||||
if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) {
|
||||
set_value(QUARKX1000_IC_ENABLE,
|
||||
QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable controller */
|
||||
set_value(QUARKX1000_IC_ENABLE,
|
||||
QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0);
|
||||
|
||||
/* Restore interrupt mask */
|
||||
write(QUARKX1000_IC_INTR_MASK, intr_mask_stat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
quarkX1000_i2c_polling_write(uint8_t *buf, uint8_t len, uint16_t addr)
|
||||
{
|
||||
device.direction = I2C_DIRECTION_WRITE;
|
||||
return i2c_polling_operation(buf, len, 0, 0, addr);
|
||||
}
|
||||
|
||||
int
|
||||
quarkX1000_i2c_polling_read(uint8_t *buf, uint8_t len, uint16_t addr)
|
||||
{
|
||||
device.direction = I2C_DIRECTION_READ;
|
||||
return i2c_polling_operation(0, 0, buf, len ,addr);
|
||||
}
|
||||
|
||||
int
|
||||
quarkX1000_i2c_is_available(void)
|
||||
{
|
||||
return inited;
|
||||
}
|
||||
|
||||
DEFINE_SHARED_IRQ(I2C_IRQ, IRQAGENT3, INTC, PIRQC, i2c_isr);
|
||||
|
||||
int
|
||||
quarkX1000_i2c_init(void)
|
||||
{
|
||||
pci_config_addr_t pci_addr;
|
||||
|
||||
pci_addr.raw = 0;
|
||||
pci_addr.bus = 0;
|
||||
pci_addr.dev = 21;
|
||||
pci_addr.func = 2;
|
||||
pci_addr.reg_off = PCI_CONFIG_REG_BAR0;
|
||||
|
||||
pci_command_enable(pci_addr, PCI_CMD_1_MEM_SPACE_EN);
|
||||
|
||||
PROT_DOMAINS_INIT_ID(drv);
|
||||
pci_init(&drv, pci_addr, MMIO_SZ, 0, 0);
|
||||
SYSCALLS_INIT(quarkX1000_i2c_mmin);
|
||||
SYSCALLS_AUTHZ(quarkX1000_i2c_mmin, drv);
|
||||
SYSCALLS_INIT(quarkX1000_i2c_mmout);
|
||||
SYSCALLS_AUTHZ(quarkX1000_i2c_mmout, drv);
|
||||
|
||||
inited = 1;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_QUARKX1000_I2C_H_
|
||||
#define CPU_X86_DRIVERS_QUARKX1000_I2C_H_
|
||||
|
||||
#include "pci.h"
|
||||
|
||||
typedef enum {
|
||||
QUARKX1000_I2C_SPEED_STANDARD,
|
||||
QUARKX1000_I2C_SPEED_FAST
|
||||
} QUARKX1000_I2C_SPEED;
|
||||
|
||||
typedef enum {
|
||||
QUARKX1000_I2C_ADDR_MODE_7BIT,
|
||||
QUARKX1000_I2C_ADDR_MODE_10BIT
|
||||
} QUARKX1000_I2C_ADDR_MODE;
|
||||
|
||||
typedef void (*quarkX1000_i2c_callback)(void);
|
||||
|
||||
int quarkX1000_i2c_init(void);
|
||||
void quarkX1000_i2c_configure(QUARKX1000_I2C_SPEED speed,
|
||||
QUARKX1000_I2C_ADDR_MODE addressing_mode);
|
||||
void quarkX1000_i2c_set_callbacks(quarkX1000_i2c_callback rx,
|
||||
quarkX1000_i2c_callback tx,
|
||||
quarkX1000_i2c_callback err);
|
||||
int quarkX1000_i2c_is_available(void);
|
||||
|
||||
int quarkX1000_i2c_read(uint8_t *buf, uint8_t len, uint16_t addr);
|
||||
int quarkX1000_i2c_write(uint8_t *buf, uint8_t len, uint16_t addr);
|
||||
|
||||
int quarkX1000_i2c_polling_read(uint8_t *buf, uint8_t len, uint16_t addr);
|
||||
int quarkX1000_i2c_polling_write(uint8_t *buf, uint8_t len, uint16_t addr);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_QUARKX1000_I2C_H_ */
|
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "dma.h"
|
||||
#include "imr.h"
|
||||
#include "msg-bus.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
quarkX1000_imr_conf(void)
|
||||
{
|
||||
quarkX1000_imr_t imr;
|
||||
int imr_idx = 0;
|
||||
|
||||
imr.lo.raw = 0;
|
||||
imr.hi.raw = 0;
|
||||
imr.rdmsk.raw = 0;
|
||||
imr.wrmsk.raw = 0;
|
||||
|
||||
imr.lo.lock = 1;
|
||||
|
||||
imr.rdmsk.cpu0 = imr.rdmsk.cpu_0 = 1;
|
||||
imr.wrmsk.cpu0 = imr.wrmsk.cpu_0 = 1;
|
||||
|
||||
quarkX1000_msg_bus_init();
|
||||
|
||||
imr.lo.addr = 0;
|
||||
imr.hi.addr = (((uint32_t)&_sbss_dma_addr) - 1) >> QUARKX1000_IMR_SHAMT;
|
||||
quarkX1000_imr_write(imr_idx, imr);
|
||||
imr_idx++;
|
||||
|
||||
imr.lo.addr = ((uint32_t)&_ebss_dma_addr) >> QUARKX1000_IMR_SHAMT;
|
||||
imr.hi.addr = ~0;
|
||||
quarkX1000_imr_write(imr_idx, imr);
|
||||
imr_idx++;
|
||||
|
||||
imr.lo.addr = 0;
|
||||
imr.hi.addr = 0;
|
||||
imr.rdmsk.raw = ~0;
|
||||
imr.wrmsk.raw = ~0;
|
||||
|
||||
/* Lock the other IMRs open */
|
||||
while(imr_idx < QUARKX1000_IMR_CNT) {
|
||||
quarkX1000_imr_write(imr_idx, imr);
|
||||
imr_idx++;
|
||||
}
|
||||
|
||||
#ifndef DBG_IMRS
|
||||
/* The IMRs are locked by the hardware, but the message bus could still
|
||||
* provide access to other potentially-sensitive functionality.
|
||||
*/
|
||||
quarkX1000_msg_bus_lock();
|
||||
#endif
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_QUARKX1000_IMR_CONF_H_
|
||||
#define CPU_X86_DRIVERS_QUARKX1000_IMR_CONF_H_
|
||||
|
||||
void quarkX1000_imr_conf(void);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_QUARKX1000_IMR_CONF_H_ */
|
|
@ -1,89 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include "imr.h"
|
||||
#include "msg-bus.h"
|
||||
|
||||
#define MEM_MANAGER_PORT 5
|
||||
|
||||
#define IMR_BASE_OFFSET 0x40
|
||||
#define IMR_REG_COUNT 4
|
||||
|
||||
#define IMR_LO_OFFSET 0
|
||||
#define IMR_HI_OFFSET 1
|
||||
#define IMR_RDMSK_OFFSET 2
|
||||
#define IMR_WRMSK_OFFSET 3
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Read the contents of the specified IMR.
|
||||
*/
|
||||
quarkX1000_imr_t
|
||||
quarkX1000_imr_read(uint32_t imr_idx)
|
||||
{
|
||||
quarkX1000_imr_t imr;
|
||||
uint32_t reg_base = IMR_BASE_OFFSET + (IMR_REG_COUNT * imr_idx);
|
||||
|
||||
assert(imr_idx < QUARKX1000_IMR_CNT);
|
||||
|
||||
quarkX1000_msg_bus_read(MEM_MANAGER_PORT,
|
||||
reg_base + IMR_LO_OFFSET, &imr.lo.raw);
|
||||
quarkX1000_msg_bus_read(MEM_MANAGER_PORT,
|
||||
reg_base + IMR_HI_OFFSET, &imr.hi.raw);
|
||||
quarkX1000_msg_bus_read(MEM_MANAGER_PORT,
|
||||
reg_base + IMR_RDMSK_OFFSET, &imr.rdmsk.raw);
|
||||
quarkX1000_msg_bus_read(MEM_MANAGER_PORT,
|
||||
reg_base + IMR_WRMSK_OFFSET, &imr.wrmsk.raw);
|
||||
|
||||
return imr;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Overwrite the contents of the specified IMR.
|
||||
*/
|
||||
void
|
||||
quarkX1000_imr_write(uint32_t imr_idx, quarkX1000_imr_t imr)
|
||||
{
|
||||
uint32_t reg_base = IMR_BASE_OFFSET + (IMR_REG_COUNT * imr_idx);
|
||||
|
||||
assert(imr_idx < QUARKX1000_IMR_CNT);
|
||||
|
||||
quarkX1000_msg_bus_write(MEM_MANAGER_PORT,
|
||||
reg_base + IMR_HI_OFFSET, imr.hi.raw);
|
||||
quarkX1000_msg_bus_write(MEM_MANAGER_PORT,
|
||||
reg_base + IMR_RDMSK_OFFSET, imr.rdmsk.raw);
|
||||
quarkX1000_msg_bus_write(MEM_MANAGER_PORT,
|
||||
reg_base + IMR_WRMSK_OFFSET, imr.wrmsk.raw);
|
||||
/* This register must be programmed last, in case it sets the lock bit. */
|
||||
quarkX1000_msg_bus_write(MEM_MANAGER_PORT,
|
||||
reg_base + IMR_LO_OFFSET, imr.lo.raw);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,125 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_QUARKX1000_IMR_H_
|
||||
#define CPU_X86_DRIVERS_QUARKX1000_IMR_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef union quarkX1000_imr_lo {
|
||||
struct {
|
||||
uint32_t : 2;
|
||||
uint32_t addr : 22;
|
||||
uint32_t : 7;
|
||||
uint32_t lock : 1;
|
||||
};
|
||||
uint32_t raw;
|
||||
} quarkX1000_imr_lo_t;
|
||||
|
||||
typedef union quarkX1000_imr_hi {
|
||||
struct {
|
||||
uint32_t : 2;
|
||||
uint32_t addr : 22;
|
||||
uint32_t : 8;
|
||||
};
|
||||
uint32_t raw;
|
||||
} quarkX1000_imr_hi_t;
|
||||
|
||||
/* Amount to shift imr_lo/hi.addr left to obtain the bound address */
|
||||
#define QUARKX1000_IMR_SHAMT 10
|
||||
|
||||
typedef union quarkX1000_imr_rdmsk {
|
||||
struct {
|
||||
uint32_t cpu0 : 1;
|
||||
uint32_t cpu_0 : 1;
|
||||
uint32_t : 6;
|
||||
uint32_t vc0_sai_id0 : 1;
|
||||
uint32_t vc0_sai_id1 : 1;
|
||||
uint32_t vc0_sai_id2 : 1;
|
||||
uint32_t vc0_sai_id3 : 1;
|
||||
uint32_t vc1_sai_id0 : 1;
|
||||
uint32_t vc1_sai_id1 : 1;
|
||||
uint32_t vc1_sai_id2 : 1;
|
||||
uint32_t vc1_sai_id3 : 1;
|
||||
uint32_t : 13;
|
||||
uint32_t punit : 1;
|
||||
uint32_t : 1;
|
||||
uint32_t esram_flush_init : 1;
|
||||
};
|
||||
uint32_t raw;
|
||||
} quarkX1000_imr_rdmsk_t;
|
||||
|
||||
typedef union quarkX1000_imr_wrmsk {
|
||||
struct {
|
||||
uint32_t cpu0 : 1;
|
||||
uint32_t cpu_0 : 1;
|
||||
uint32_t : 6;
|
||||
uint32_t vc0_sai_id0 : 1;
|
||||
uint32_t vc0_sai_id1 : 1;
|
||||
uint32_t vc0_sai_id2 : 1;
|
||||
uint32_t vc0_sai_id3 : 1;
|
||||
uint32_t vc1_sai_id0 : 1;
|
||||
uint32_t vc1_sai_id1 : 1;
|
||||
uint32_t vc1_sai_id2 : 1;
|
||||
uint32_t vc1_sai_id3 : 1;
|
||||
uint32_t : 13;
|
||||
uint32_t punit : 1;
|
||||
uint32_t cpu_snoop : 1;
|
||||
uint32_t esram_flush_init : 1;
|
||||
};
|
||||
uint32_t raw;
|
||||
} quarkX1000_imr_wrmsk_t;
|
||||
|
||||
/* Refer to Intel Quark SoC X1000 Datasheet, Section 12.7.4 for more details on
|
||||
* the IMR registers.
|
||||
*/
|
||||
typedef struct quarkX1000_imr {
|
||||
quarkX1000_imr_lo_t lo;
|
||||
quarkX1000_imr_hi_t hi;
|
||||
quarkX1000_imr_rdmsk_t rdmsk;
|
||||
quarkX1000_imr_wrmsk_t wrmsk;
|
||||
} quarkX1000_imr_t;
|
||||
|
||||
/* The Intel Quark SoC X1000 defines eight general IMRs. */
|
||||
#define QUARKX1000_IMR_CNT 8
|
||||
|
||||
/* Routines for accessing the Isolated Memory Region (IMR) feature.
|
||||
*
|
||||
* The Intel Quark X1000 SoC includes support for Isolated Memory Regions
|
||||
* (IMRs), which are specified using range registers and associated
|
||||
* control registers that are accessible via the message bus.
|
||||
*
|
||||
* Refer to Intel Quark SoC X1000 Datasheet, Section 12.2 for more information.
|
||||
*/
|
||||
|
||||
quarkX1000_imr_t quarkX1000_imr_read(uint32_t imr_idx);
|
||||
void quarkX1000_imr_write(uint32_t imr_idx, quarkX1000_imr_t imr);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_QUARKX1000_IMR_H_ */
|
|
@ -1,143 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "msg-bus.h"
|
||||
#include "pci.h"
|
||||
#include "syscalls.h"
|
||||
|
||||
PROT_DOMAINS_ALLOC(dom_client_data_t, quarkX1000_msg_bus);
|
||||
|
||||
/** Message bus control register */
|
||||
#define MCR_PCI_REG_ADDR 0xD0
|
||||
/** Message data register */
|
||||
#define MDR_PCI_REG_ADDR 0xD4
|
||||
/** Message control register extension */
|
||||
#define MCRX_PCI_REG_ADDR 0xD8
|
||||
|
||||
typedef union mcr {
|
||||
struct {
|
||||
uint32_t : 4;
|
||||
uint32_t byte_en : 4;
|
||||
uint32_t reg_off : 8;
|
||||
uint32_t port : 8;
|
||||
uint32_t opcode : 8;
|
||||
};
|
||||
uint32_t raw;
|
||||
} mcr_t;
|
||||
|
||||
typedef union mcrx {
|
||||
struct {
|
||||
uint32_t : 8;
|
||||
uint32_t reg_off : 24;
|
||||
};
|
||||
uint32_t raw;
|
||||
} mcrx_t;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
request_op(uint8_t port, uint32_t reg_off, uint8_t opcode)
|
||||
{
|
||||
pci_config_addr_t pci_addr = { .raw = 0 };
|
||||
mcr_t mcr = { .raw = 0 };
|
||||
mcrx_t mcrx = { .raw = 0 };
|
||||
|
||||
pci_addr.reg_off = MCR_PCI_REG_ADDR;
|
||||
mcr.opcode = opcode;
|
||||
mcr.byte_en = 0xF;
|
||||
mcr.port = port;
|
||||
mcr.reg_off = reg_off & 0xFF;
|
||||
pci_config_write(pci_addr, mcr.raw);
|
||||
|
||||
pci_addr.reg_off = MCRX_PCI_REG_ADDR;
|
||||
mcrx.reg_off = reg_off >> 8;
|
||||
pci_config_write(pci_addr, mcrx.raw);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Read from a message bus register.
|
||||
* \param port Port of message bus register to be read.
|
||||
* \param reg_off Register/offset identifier of message bus register to read.
|
||||
* \param val Storage location for value that has been read.
|
||||
*/
|
||||
SYSCALLS_DEFINE_SINGLETON(quarkX1000_msg_bus_read,
|
||||
quarkX1000_msg_bus,
|
||||
uint8_t port,
|
||||
uint32_t reg_off,
|
||||
uint32_t *val)
|
||||
{
|
||||
uint32_t *loc_val;
|
||||
pci_config_addr_t pci_addr = { .raw = 0 };
|
||||
|
||||
PROT_DOMAINS_VALIDATE_PTR(loc_val, val, sizeof(*val));
|
||||
|
||||
request_op(port, reg_off, 0x10);
|
||||
|
||||
pci_addr.reg_off = MDR_PCI_REG_ADDR;
|
||||
*loc_val = pci_config_read(pci_addr);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Write to a message bus register.
|
||||
* \param port Port of message bus register to be written.
|
||||
* \param reg_off Register/offset identifier of message bus register to write.
|
||||
* \param val Value to write.
|
||||
*/
|
||||
SYSCALLS_DEFINE_SINGLETON(quarkX1000_msg_bus_write,
|
||||
quarkX1000_msg_bus,
|
||||
uint8_t port,
|
||||
uint32_t reg_off,
|
||||
uint32_t val)
|
||||
{
|
||||
pci_config_addr_t pci_addr = { .raw = 0 };
|
||||
|
||||
pci_addr.reg_off = MDR_PCI_REG_ADDR;
|
||||
pci_config_write(pci_addr, val);
|
||||
|
||||
request_op(port, reg_off, 0x11);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
quarkX1000_msg_bus_init(void)
|
||||
{
|
||||
PROT_DOMAINS_INIT_ID(quarkX1000_msg_bus);
|
||||
prot_domains_reg(&quarkX1000_msg_bus, 0, 0, 0, 0, true);
|
||||
SYSCALLS_INIT(quarkX1000_msg_bus_read);
|
||||
SYSCALLS_AUTHZ(quarkX1000_msg_bus_read, quarkX1000_msg_bus);
|
||||
SYSCALLS_INIT(quarkX1000_msg_bus_write);
|
||||
SYSCALLS_AUTHZ(quarkX1000_msg_bus_write, quarkX1000_msg_bus);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
quarkX1000_msg_bus_lock(void)
|
||||
{
|
||||
SYSCALLS_DEAUTHZ(quarkX1000_msg_bus_read, quarkX1000_msg_bus);
|
||||
SYSCALLS_DEAUTHZ(quarkX1000_msg_bus_write, quarkX1000_msg_bus);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_QUARKX1000_MSG_BUS_H_
|
||||
#define CPU_X86_DRIVERS_QUARKX1000_MSG_BUS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* Routines for accessing the message bus.
|
||||
*
|
||||
* The Intel Quark X1000 SoC includes a message bus that is accessible
|
||||
* via PCI configuration registers. It communicates to various SoC
|
||||
* components such as the Isolated Memory Region (IMR) registers and the
|
||||
* Remote Management Unit.
|
||||
*
|
||||
* Refer to Intel Quark SoC X1000 Datasheet, Section 12.5 for more details on
|
||||
* the message bus.
|
||||
*/
|
||||
|
||||
void quarkX1000_msg_bus_init(void);
|
||||
void quarkX1000_msg_bus_lock(void);
|
||||
void quarkX1000_msg_bus_read(uint8_t port, uint32_t reg_off, uint32_t *val);
|
||||
void quarkX1000_msg_bus_write(uint8_t port, uint32_t reg_off, uint32_t val);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_QUARKX1000_MSG_BUS_H_ */
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "uart.h"
|
||||
#include "uart-16x50.h"
|
||||
#include <assert.h>
|
||||
|
||||
PROT_DOMAINS_ALLOC(uart_16x50_driver_t, quarkX1000_uart0);
|
||||
PROT_DOMAINS_ALLOC(uart_16x50_driver_t, quarkX1000_uart1);
|
||||
|
||||
/* UART base frequency from section 18.2.2 of Intel Quark SoC X1000
|
||||
* Datasheet.
|
||||
*/
|
||||
#define QUARK_X1000_UART_FBASE 44236800
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Perform common initialization that must precede per-port
|
||||
* initialization.
|
||||
*/
|
||||
void
|
||||
quarkX1000_uart_init(void)
|
||||
{
|
||||
uart_16x50_init();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Initialize a UART.
|
||||
* \param dev Device to initialize.
|
||||
*/
|
||||
void
|
||||
quarkX1000_uart_init_port(quarkX1000_uart_dev_t dev, unsigned baud)
|
||||
{
|
||||
uint16_t dl;
|
||||
pci_config_addr_t pci_addr;
|
||||
uart_16x50_driver_t ATTR_KERN_ADDR_SPACE *drv;
|
||||
|
||||
assert((dev == QUARK_X1000_UART_0) || (dev == QUARK_X1000_UART_1));
|
||||
|
||||
pci_addr.raw = 0;
|
||||
|
||||
/* PCI addresses from section 18.4 of Intel Quark SoC X1000 Datasheet. */
|
||||
pci_addr.dev = 20;
|
||||
pci_addr.func = (dev == QUARK_X1000_UART_0) ? 1 : 5;
|
||||
pci_addr.reg_off = PCI_CONFIG_REG_BAR0;
|
||||
|
||||
if(dev == QUARK_X1000_UART_0) {
|
||||
drv = &quarkX1000_uart0;
|
||||
PROT_DOMAINS_INIT_ID(quarkX1000_uart0);
|
||||
} else {
|
||||
drv = &quarkX1000_uart1;
|
||||
PROT_DOMAINS_INIT_ID(quarkX1000_uart1);
|
||||
}
|
||||
/* Divisor setting from section 18.2.2 of Intel Quark SoC X1000 Datasheet. */
|
||||
dl = QUARK_X1000_UART_FBASE / (16 * baud);
|
||||
uart_16x50_init_port(drv, pci_addr, dl);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Transmit a character via a UART.
|
||||
* \param dev Device to use.
|
||||
* \param c Character to transmit.
|
||||
*/
|
||||
void
|
||||
quarkX1000_uart_tx(quarkX1000_uart_dev_t dev, uint8_t c)
|
||||
{
|
||||
uart_16x50_driver_t drv;
|
||||
assert((dev == QUARK_X1000_UART_0) || (dev == QUARK_X1000_UART_1));
|
||||
prot_domains_copy_dcd(&drv,
|
||||
(dev == QUARK_X1000_UART_0) ?
|
||||
&quarkX1000_uart0 : &quarkX1000_uart1);
|
||||
uart_16x50_tx(drv, c);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_QUARKX1000_UART_H_
|
||||
#define CPU_X86_DRIVERS_QUARKX1000_UART_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
QUARK_X1000_UART_0,
|
||||
QUARK_X1000_UART_1
|
||||
} quarkX1000_uart_dev_t;
|
||||
|
||||
void quarkX1000_uart_init(void);
|
||||
void quarkX1000_uart_init_port(quarkX1000_uart_dev_t dev, unsigned baud);
|
||||
void quarkX1000_uart_tx(quarkX1000_uart_dev_t dev, uint8_t c);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_QUARKX1000_UART_H_ */
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
.text
|
||||
|
||||
.global halt
|
||||
halt:
|
||||
cli
|
||||
die: hlt
|
||||
jmp die
|
||||
|
||||
.global outb
|
||||
outb:
|
||||
mov 4(%esp), %dx
|
||||
mov 8(%esp), %al
|
||||
out %al, %dx
|
||||
ret
|
||||
|
||||
.global outl
|
||||
outl:
|
||||
mov 4(%esp), %dx
|
||||
mov 8(%esp), %eax
|
||||
out %eax, %dx
|
||||
ret
|
||||
|
||||
.global inb
|
||||
inb:
|
||||
mov 4(%esp), %dx
|
||||
in %dx, %al
|
||||
ret
|
||||
|
||||
.global inl
|
||||
inl:
|
||||
mov 4(%esp), %dx
|
||||
in %dx, %eax
|
||||
ret
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef HELPERS_H
|
||||
#define HELPERS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define BIT(n) (1UL << (n))
|
||||
|
||||
void halt(void) __attribute__((__noreturn__));
|
||||
|
||||
#define STRINGIFY(x) #x
|
||||
/* The C preprocessor will not expand macro arguments that are converted to
|
||||
* strings in the macro body using the '#' operator. The EXP_STRINGIFY macro
|
||||
* introduces an additional level of argument expansion for instances where
|
||||
* the developer wishes to convert the expanded argument to a string.
|
||||
*/
|
||||
#define EXP_STRINGIFY(x) STRINGIFY(x)
|
||||
|
||||
#define ALIGN(x, amt) \
|
||||
(((x) & ~((amt) - 1)) + ((((x) & ((amt) - 1)) == 0) ? 0 : (amt)))
|
||||
|
||||
/** Wrappers for the assembly 'out' instruction. */
|
||||
void outb(uint16_t port, uint8_t val);
|
||||
void outl(uint16_t port, uint32_t val);
|
||||
|
||||
/** Wrappers for the assembly 'in' instruction */
|
||||
uint8_t inb(uint16_t port);
|
||||
uint32_t inl(uint16_t port);
|
||||
|
||||
#endif /* HELPERS_H */
|
|
@ -1,124 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
#include "gdt.h"
|
||||
#include "helpers.h"
|
||||
#include "idt.h"
|
||||
#include "interrupt.h"
|
||||
#include "irq.h"
|
||||
#include "stacks.h"
|
||||
|
||||
static void
|
||||
double_fault_handler(struct interrupt_context context)
|
||||
{
|
||||
halt();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* The OS has switched to its own segment descriptors. When multi-segment
|
||||
* protection domain support is enabled, this routine runs with the
|
||||
* necessary address translations configured to invoke other routines that
|
||||
* require those translations to be in place. However, the protection domain
|
||||
* support, if enabled, has not yet been fully activated.
|
||||
*/
|
||||
static void
|
||||
boot_stage1(void)
|
||||
{
|
||||
idt_init();
|
||||
|
||||
/* Set an interrupt handler for Double Fault exception. This way, we avoid
|
||||
* the system to triple fault, leaving no trace about what happened.
|
||||
*/
|
||||
SET_EXCEPTION_HANDLER(8, 1, double_fault_handler);
|
||||
|
||||
/* Initialize protection domain support, if enabled */
|
||||
prot_domains_init();
|
||||
|
||||
prot_domains_leave_boot_stage1();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int main(void);
|
||||
/* This routine runs with the initial, flat address space, even if protection
|
||||
* domain support is enabled. The goal behind the design of this routine is to
|
||||
* keep it as short as possible, since it is unable to directly reference data
|
||||
* and invoke functions that are intended to be accessible later after the
|
||||
* system has booted when a multi-segment protection domain model is in use.
|
||||
*/
|
||||
void
|
||||
cpu_boot_stage0(void)
|
||||
{
|
||||
/* Reserve three stack slots for return addresses */
|
||||
uintptr_t top_of_stack = STACKS_INIT_TOP;
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE
|
||||
uintptr_t *top_of_stack_ptr =
|
||||
(uintptr_t *)DATA_OFF_TO_PHYS_ADDR(top_of_stack);
|
||||
|
||||
top_of_stack_ptr[0] = (uintptr_t)prot_domains_launch_kernel;
|
||||
top_of_stack_ptr[1] = (uintptr_t)prot_domains_launch_app;
|
||||
#endif
|
||||
|
||||
/* Perform common GDT initialization */
|
||||
gdt_init();
|
||||
|
||||
/* Switch all data segment registers to the newly-initialized flat data
|
||||
* descriptor.
|
||||
*/
|
||||
__asm__(
|
||||
"mov %0, %%ds\n\t"
|
||||
"mov %0, %%es\n\t"
|
||||
"mov %0, %%fs\n\t"
|
||||
"mov %0, %%gs\n\t"
|
||||
:
|
||||
: "r" (GDT_SEL_DATA_FLAT)
|
||||
);
|
||||
|
||||
/**
|
||||
* Perform specific GDT initialization tasks for the protection domain
|
||||
* implementation that is enabled, if any.
|
||||
*/
|
||||
prot_domains_gdt_init();
|
||||
|
||||
/* Do not pass memory operands to the asm block below, since it is
|
||||
* switching from the flat address space to a multi-segment address space
|
||||
* model if such a model is used by the enabled protection domain
|
||||
* implementation, if any.
|
||||
*/
|
||||
__asm__(
|
||||
"mov %[_ss_], %%ss\n\t"
|
||||
"mov %[_esp_], %%esp\n\t"
|
||||
"ljmp %[_cs_], %[_stage1_]\n\t"
|
||||
:
|
||||
: [_ss_] "r" (GDT_SEL_STK_EXC),
|
||||
[_esp_] "r" (top_of_stack),
|
||||
[_cs_] "i" ((uint16_t)GDT_SEL_CODE_EXC),
|
||||
[_stage1_] "i" (boot_stage1)
|
||||
);
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_H
|
||||
#define CPU_H
|
||||
|
||||
#include "prot-domains.h"
|
||||
|
||||
void cpu_boot_stage0(void) ATTR_CODE_BOOT;
|
||||
|
||||
#endif /* CPU_H */
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gdt.h"
|
||||
#include "gdt-layout.h"
|
||||
#include "helpers.h"
|
||||
#include "prot-domains.h"
|
||||
#include "segmentation.h"
|
||||
|
||||
#define GDT_MEM_PL0 (SEG_DESCTYPE_NSYS | SEG_GRAN_PAGE)
|
||||
#define GDT_CODE_PL0 (GDT_MEM_PL0 | SEG_TYPE_CODE_EXRD)
|
||||
#define GDT_DATA_PL0 (GDT_MEM_PL0 | SEG_TYPE_DATA_RDWR)
|
||||
|
||||
typedef struct gdtr
|
||||
{
|
||||
uint16_t limit;
|
||||
uint32_t base;
|
||||
} __attribute__((packed)) gdtr_t;
|
||||
|
||||
/* From Intel Combined Manual, Vol. 3 , Section 3.5.1: The base addresses of
|
||||
* the GDT should be aligned on an eight-byte boundary to yield the best
|
||||
* processor performance.
|
||||
*/
|
||||
segment_desc_t __attribute__ ((aligned(8))) ATTR_BSS_GDT_START
|
||||
gdt[GDT_NUM_FIXED_DESC];
|
||||
|
||||
#define GDT_LEN \
|
||||
((((uintptr_t)&_ebss_gdt_addr) - \
|
||||
(uintptr_t)gdt)/sizeof(segment_desc_t))
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void ATTR_CODE_BOOT
|
||||
set_descriptor(unsigned int index,
|
||||
uint32_t base,
|
||||
uint32_t len,
|
||||
uint16_t flag)
|
||||
{
|
||||
segment_desc_t descriptor;
|
||||
|
||||
if(GDT_LEN <= index) {
|
||||
halt();
|
||||
}
|
||||
|
||||
segment_desc_init(&descriptor, base, len, flag);
|
||||
|
||||
/* Save descriptor into gdt */
|
||||
gdt_insert_boot(index, descriptor);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
gdt_copy_desc_change_dpl(unsigned int dest_idx,
|
||||
unsigned int src_idx,
|
||||
unsigned dpl)
|
||||
{
|
||||
segment_desc_t desc;
|
||||
|
||||
if((GDT_LEN <= dest_idx) || (GDT_LEN <= src_idx)) {
|
||||
halt();
|
||||
}
|
||||
|
||||
gdt_lookup(src_idx, &desc);
|
||||
SEG_SET_FLAG(desc, DPL, dpl);
|
||||
gdt_insert(dest_idx, desc);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* This function initializes the Global Descriptor Table. For simplicity, the
|
||||
* memory is initially organized following the flat model. Thus, memory appears
|
||||
* to Contiki as a single continuous address space. Code, data, and stack
|
||||
* are all contained in this address space (so called linear address space).
|
||||
* Certain protection domain implementations switch to a multi-segment memory
|
||||
* model later during boot.
|
||||
*/
|
||||
void
|
||||
gdt_init(void)
|
||||
{
|
||||
gdtr_t gdtr;
|
||||
|
||||
/* Initialize gdtr structure */
|
||||
gdtr.limit = sizeof(segment_desc_t) * GDT_LEN - 1;
|
||||
gdtr.base = KERN_DATA_OFF_TO_PHYS_ADDR(gdt);
|
||||
|
||||
/* Initialize descriptors */
|
||||
set_descriptor(GDT_IDX_NULL, 0, 0, 0);
|
||||
set_descriptor(GDT_IDX_CODE_FLAT, 0, 0x100000, GDT_CODE_PL0);
|
||||
set_descriptor(GDT_IDX_DATA_FLAT, 0, 0x100000, GDT_DATA_PL0);
|
||||
|
||||
/* Load GDTR */
|
||||
__asm__ __volatile__ ("lgdt %0" :: "m" (gdtr));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
gdt_insert_boot(unsigned int idx, segment_desc_t desc)
|
||||
{
|
||||
((segment_desc_t *)KERN_DATA_OFF_TO_PHYS_ADDR(gdt))[idx] = desc;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
gdt_insert(unsigned int idx, segment_desc_t desc)
|
||||
{
|
||||
if(GDT_LEN <= idx) {
|
||||
halt();
|
||||
}
|
||||
|
||||
KERN_WRITEL(gdt[idx].raw_lo, desc.raw_lo);
|
||||
KERN_WRITEL(gdt[idx].raw_hi, desc.raw_hi);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
gdt_lookup(unsigned int idx, segment_desc_t *desc)
|
||||
{
|
||||
if((GDT_LEN <= idx) || (desc == NULL)) {
|
||||
halt();
|
||||
}
|
||||
|
||||
KERN_READL(desc->raw_lo, gdt[idx].raw_lo);
|
||||
KERN_READL(desc->raw_hi, gdt[idx].raw_hi);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef GDT_H
|
||||
#define GDT_H
|
||||
|
||||
#include "gdt-layout.h"
|
||||
#include "prot-domains.h"
|
||||
#include "segmentation.h"
|
||||
|
||||
extern segment_desc_t ATTR_KERN_ADDR_SPACE gdt[];
|
||||
extern int ATTR_KERN_ADDR_SPACE _ebss_gdt_addr;
|
||||
|
||||
#define GDT_IDX_OF_DESC(ptr) \
|
||||
((((uintptr_t)(ptr)) - ((uintptr_t)&gdt))/ \
|
||||
sizeof(segment_desc_t))
|
||||
|
||||
typedef struct far_pointer {
|
||||
/** Far pointer offset. */
|
||||
uint32_t offset;
|
||||
/** Far pointer segment/gate selector. */
|
||||
uint16_t sel;
|
||||
uint16_t pad;
|
||||
} __attribute__((packed)) far_pointer_t;
|
||||
|
||||
/**
|
||||
* \brief Compute the selector for a GDT entry allocated somewhere besides gdt.c.
|
||||
* \param ptr Pointer to GDT descriptor.
|
||||
* \param rpl Requested Privilege Level.
|
||||
*/
|
||||
#define GDT_SEL_OF_DESC(ptr, rpl) GDT_SEL(GDT_IDX_OF_DESC(ptr), rpl)
|
||||
|
||||
/* Section for fixed GDT entries */
|
||||
#define ATTR_BSS_GDT \
|
||||
__attribute__((section(".gdt_bss"))) ATTR_KERN_ADDR_SPACE
|
||||
/* Section for TSS and LDT descriptors for protection domains */
|
||||
#define ATTR_BSS_GDT_MID \
|
||||
__attribute__((used, section(".gdt_bss_mid"))) ATTR_KERN_ADDR_SPACE
|
||||
/* Section for other GDT entries */
|
||||
#define ATTR_BSS_GDT_START \
|
||||
__attribute__((section(".gdt_bss_start"))) ATTR_KERN_ADDR_SPACE
|
||||
|
||||
void gdt_copy_desc_change_dpl(unsigned int dest_idx,
|
||||
unsigned int src_idx,
|
||||
unsigned dpl);
|
||||
void gdt_init(void) ATTR_CODE_BOOT;
|
||||
void gdt_insert(unsigned int idx, segment_desc_t desc);
|
||||
void gdt_insert_boot(unsigned int idx, segment_desc_t desc) ATTR_CODE_BOOT;
|
||||
void gdt_lookup(unsigned int idx, segment_desc_t *desc);
|
||||
|
||||
#endif /* GDT_H */
|
|
@ -1,112 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gdt-layout.h"
|
||||
#include "prot-domains.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "helpers.h"
|
||||
#include "segmentation.h"
|
||||
#include "idt.h"
|
||||
|
||||
#define NUM_DESC 256
|
||||
|
||||
typedef struct idtr {
|
||||
uint16_t limit;
|
||||
uint32_t base;
|
||||
} __attribute__((packed)) idtr_t;
|
||||
|
||||
typedef union intr_gate_desc {
|
||||
struct __attribute__((packed)) {
|
||||
uint16_t offset_low;
|
||||
uint16_t selector; /* Segment Selector for destination code segment */
|
||||
uint16_t fixed:11;
|
||||
uint16_t d:1; /* Size of gate: 1 = 32 bits; 0 = 16 bits */
|
||||
uint16_t pad:1;
|
||||
uint16_t dpl:2; /* Descriptor Privilege Level */
|
||||
uint16_t p:1; /* Segment Present flag */
|
||||
uint16_t offset_high;
|
||||
};
|
||||
uint64_t raw;
|
||||
struct {
|
||||
uint32_t raw_lo;
|
||||
uint32_t raw_hi;
|
||||
};
|
||||
} intr_gate_desc_t;
|
||||
|
||||
/* According to Intel Combined Manual, Vol. 3, Section 6.10, the base addresses
|
||||
* of the IDT should be aligned on an 8-byte boundary to maximize performance
|
||||
* of cache line fills.
|
||||
*/
|
||||
static intr_gate_desc_t __attribute__((aligned(8))) ATTR_BSS_KERN
|
||||
idt[NUM_DESC];
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* XXX: If you change this function prototype, make sure you fix the assembly
|
||||
* code in SET_INT_EXC_HANDLER macro in interrupt.h. Otherwise, you might
|
||||
* face a very-hard-to-find bug in the interrupt handling system.
|
||||
*/
|
||||
void
|
||||
idt_set_intr_gate_desc(int intr_num,
|
||||
uint32_t offset,
|
||||
uint16_t cs,
|
||||
uint16_t dpl)
|
||||
{
|
||||
intr_gate_desc_t desc;
|
||||
|
||||
desc.offset_low = offset & 0xFFFF;
|
||||
desc.selector = cs;
|
||||
desc.fixed = BIT(9) | BIT(10);
|
||||
desc.pad = 0;
|
||||
desc.d = 1;
|
||||
desc.dpl = dpl;
|
||||
desc.p = 1;
|
||||
desc.offset_high = (offset >> 16) & 0xFFFF;
|
||||
|
||||
KERN_WRITEL(idt[intr_num].raw_hi, desc.raw_hi);
|
||||
KERN_WRITEL(idt[intr_num].raw_lo, desc.raw_lo);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Initialize Interrupt Descriptor Table. The IDT is initialized with
|
||||
* null descriptors. Therefore, any interrupt at this point will cause
|
||||
* a triple fault.
|
||||
*/
|
||||
void
|
||||
idt_init(void)
|
||||
{
|
||||
idtr_t idtr;
|
||||
|
||||
/* Initialize idtr structure */
|
||||
idtr.limit = (sizeof(intr_gate_desc_t) * NUM_DESC) - 1;
|
||||
idtr.base = KERN_DATA_OFF_TO_PHYS_ADDR((uint32_t)idt);
|
||||
|
||||
/* Load IDTR register */
|
||||
__asm__("lidt %0\n\t" :: "m" (idtr));
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef IDT_H
|
||||
#define IDT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "prot-domains.h"
|
||||
|
||||
void idt_init(void);
|
||||
void idt_set_intr_gate_desc(int intr_num,
|
||||
uint32_t offset,
|
||||
uint16_t cs,
|
||||
uint16_t dpl);
|
||||
|
||||
#endif /* IDT_H */
|
|
@ -1,148 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef INTERRUPT_H
|
||||
#define INTERRUPT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "gdt-layout.h"
|
||||
|
||||
#include "idt.h"
|
||||
|
||||
struct interrupt_context {
|
||||
/* The general-purpose register values are saved by the pushal instruction in
|
||||
* the interrupt dispatcher. Having access to these saved values may be
|
||||
* useful in some future interrupt or exception handler, and saving and later
|
||||
* restoring them also enables the ISR to freely overwrite the EAX, ECX, and
|
||||
* EDX registers as is permitted by the cdecl calling convention.
|
||||
*/
|
||||
uint32_t edi;
|
||||
uint32_t esi;
|
||||
uint32_t ebp;
|
||||
uint32_t esp;
|
||||
uint32_t ebx;
|
||||
uint32_t edx;
|
||||
uint32_t ecx;
|
||||
uint32_t eax;
|
||||
/* These two values are pushed on the stack by the CPU when it delivers an
|
||||
* exception with an associated error code. Currently, only the double fault
|
||||
* handler accepts this structure as a parameter, and that type of exception
|
||||
* does have an associated error code.
|
||||
*/
|
||||
uint32_t error_code;
|
||||
uint32_t eip;
|
||||
/* The CPU pushes additional values beyond these on the stack, specifically
|
||||
* the code segment descriptor and flags. If a privilege-level change occurs
|
||||
* during delivery, the CPU additionally pushes the stack pointer and stack
|
||||
* segment descriptor.
|
||||
*/
|
||||
};
|
||||
|
||||
#define ISR_STUB(label_str, has_error_code, handler_str, exc) \
|
||||
"jmp 2f\n\t" \
|
||||
".align 4\n\t" \
|
||||
label_str ":\n\t" \
|
||||
" pushal\n\t" \
|
||||
PROT_DOMAINS_ENTER_ISR(exc) \
|
||||
" call " handler_str "\n\t" \
|
||||
PROT_DOMAINS_LEAVE_ISR(exc) \
|
||||
" popal\n\t" \
|
||||
" .if " #has_error_code "\n\t" \
|
||||
" add $4, %%esp\n\t" \
|
||||
" .endif\n\t" \
|
||||
" iret\n\t" \
|
||||
"2:\n\t"
|
||||
|
||||
/* Helper macro to register interrupt handler function.
|
||||
*
|
||||
* num: Interrupt number (0-255)
|
||||
* has_error_code: 0 if interrupt doesn't push error code onto the
|
||||
* stack. Otherwise, set this argument to 1.
|
||||
* handler: Pointer to function that should be called once the
|
||||
* interrupt is raised. In case has_error_code == 0
|
||||
* the function prototype should be the following:
|
||||
* void handler(void)
|
||||
* Otherwise, it should be:
|
||||
* void handler(struct interrupt_context context)
|
||||
* exc: 0 if this is an interrupt, which should be handled
|
||||
* at the interrupt privilege level. 1 if this is an
|
||||
* exception, which should be handled at the
|
||||
* exception privilege level.
|
||||
* dpl: Privilege level for IDT descriptor, which is the
|
||||
* numerically-highest privilege level that can
|
||||
* generate this interrupt with a software interrupt
|
||||
* instruction.
|
||||
*
|
||||
* Since there is no easy way to write an Interrupt Service Routines
|
||||
* (ISR) in C (for further information on this, see [1]), we provide
|
||||
* this helper macro. It basically provides an assembly trampoline
|
||||
* to a C function (handler parameter) which, indeed, handles the
|
||||
* interrupt.
|
||||
*
|
||||
* [1] http://wiki.osdev.org/Interrupt_Service_Routines
|
||||
*/
|
||||
#define SET_INT_EXC_HANDLER(num, has_error_code, handler, exc, dpl) \
|
||||
do { \
|
||||
__asm__ __volatile__ ( \
|
||||
"pushl %[_dpl_]\n\t" \
|
||||
"pushl %[_cs_]\n\t" \
|
||||
"pushl $1f\n\t" \
|
||||
"pushl %[_isr_num_]\n\t" \
|
||||
"call idt_set_intr_gate_desc\n\t" \
|
||||
"add $16, %%esp\n\t" \
|
||||
ISR_STUB("1", has_error_code, "%P[_handler_]", exc) \
|
||||
: \
|
||||
: [_isr_num_] "g" (num), \
|
||||
[_handler_] "i" (handler), \
|
||||
[_cs_] "i" (exc ? GDT_SEL_CODE_EXC : GDT_SEL_CODE_INT), \
|
||||
[_dpl_] "i" (dpl) \
|
||||
/* the invocation of idt_set_intr_gate_desc may clobber */ \
|
||||
/* the caller-saved registers: */ \
|
||||
: "eax", "ecx", "edx" \
|
||||
); \
|
||||
} while (0)
|
||||
#define SET_INTERRUPT_HANDLER(num, has_error_code, handler) \
|
||||
SET_INT_EXC_HANDLER(num, has_error_code, handler, 0, PRIV_LVL_INT)
|
||||
#define SET_EXCEPTION_HANDLER(num, has_error_code, handler) \
|
||||
SET_INT_EXC_HANDLER(num, has_error_code, handler, 1, PRIV_LVL_EXC)
|
||||
|
||||
/* Disable maskable hardware interrupts */
|
||||
#define DISABLE_IRQ() \
|
||||
do { \
|
||||
__asm__ ("cli"); \
|
||||
} while (0)
|
||||
|
||||
/* Enable maskable hardware interrupts */
|
||||
#define ENABLE_IRQ() \
|
||||
do { \
|
||||
__asm__ ("sti"); \
|
||||
} while (0)
|
||||
|
||||
#endif /* INTERRUPT_H */
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef IRQ_H
|
||||
#define IRQ_H
|
||||
|
||||
void irq_init(void);
|
||||
|
||||
#endif /* IRQ_H */
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "drivers/legacy_pc/pic.h"
|
||||
#include "interrupt.h"
|
||||
#include "irq.h"
|
||||
|
||||
#define IRQ7_INT PIC_INT(7)
|
||||
|
||||
static void
|
||||
spurious_irq7_handler(void)
|
||||
{
|
||||
/*
|
||||
* NOTE: Originally IRQ7 was used for the parallel port interrupts. Nowadays,
|
||||
* though, it is only used if some other IRQ (i.e.: a PCIx interrupt) is
|
||||
* mapped to it. In this case we will have to check the PIC ISR register in
|
||||
* order to confirm this was a real interrupt.
|
||||
*
|
||||
* In case of a spurious interrupt, we should NEVER send an EOI here so the PIC
|
||||
* doesn't trigger the next queued interrupt.
|
||||
*/
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
irq_init(void)
|
||||
{
|
||||
pic_init();
|
||||
|
||||
/* Set a 'fake' handler for the Spurious IRQ7 interrupts.
|
||||
* Refer to http://wiki.osdev.org/PIC .
|
||||
*/
|
||||
SET_INTERRUPT_HANDLER(IRQ7_INT, 0, spurious_irq7_handler);
|
||||
}
|
|
@ -1,997 +0,0 @@
|
|||
X86 Lightweight Protection Domain Support for Contiki
|
||||
=====================================================
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
The X86 port of Contiki implements a simple, lightweight form of
|
||||
protection domains using a pluggable framework. Currently, there are
|
||||
three plugins available:
|
||||
|
||||
- Flat memory model with paging.
|
||||
- Multi-segment memory model with either hardware- or
|
||||
software-switched segments. The hardware-switched segments
|
||||
approach is based on Task-State Segment (TSS) structures.
|
||||
|
||||
For an introduction to paging and TSS and possible ways in which they
|
||||
can be used, refer to the following resources:
|
||||
|
||||
- Intel Combined Manual (Intel 64 and IA-32 Architectures Software
|
||||
Developer's Manual), Vol. 3, Chapter 4
|
||||
- Programming the 80386, by John H. Crawford and Patrick
|
||||
P. Gelsinger, Chapter 5
|
||||
|
||||
The overall goal of a protection domain implementation within this
|
||||
framework is to define a set of resources that should be accessible to
|
||||
each protection domain and to prevent that protection domain from
|
||||
accessing other resources. The details of each implementation of
|
||||
protection domains may differ substantially, but they should all be
|
||||
guided by the principle of least privilege [1]. However, that
|
||||
idealized principle is balanced against the practical objectives of
|
||||
limiting the number of relatively time-consuming context switches and
|
||||
minimizing changes to existing code. In fact, no changes were made to
|
||||
code outside of the CPU- and platform-specific code directories for
|
||||
the initial plugins.
|
||||
|
||||
Each protection domain can optionally be associated with a metadata
|
||||
and/or MMIO region. The hardware can support additional regions per
|
||||
protection domain, but that would increase complexity and is unneeded
|
||||
for the existing protection domains.
|
||||
|
||||
After boot, all code runs in the context of some protection domain.
|
||||
Two default protection domains are implemented:
|
||||
|
||||
- kern: Kernel protection domain that is more privileged than any
|
||||
other protection domain. As little code as possible should be placed
|
||||
in this protection domain.
|
||||
- app: Application protection domain used whenever special privileges
|
||||
are not required.
|
||||
|
||||
Additional protection domains are defined as needed. For example,
|
||||
each driver may reside in a separate protection domain, although not
|
||||
all drivers require additional privileges beyond those available in
|
||||
the relevant scheduling context in the app protection domain. The
|
||||
Ethernet and UART drivers are assigned separate protection domains.
|
||||
Non-driver protection domains can also be defined. Other drivers only
|
||||
require access to programmed IO ports accessible via the IN* and OUT*
|
||||
instructions, and such drivers do not require separate protection
|
||||
domains. They run in the Contiki preemptive scheduling context and
|
||||
the kernel protection domain, both of which are granted access to all
|
||||
IO ports.
|
||||
|
||||
Each protection domain may have associated system calls. A system
|
||||
call transfers control from a client protection domain to a defined
|
||||
entrypoint in a server protection domain. As their name suggests,
|
||||
system calls adhere to a synchronous call-return model (rather than
|
||||
some alternative such as an asynchronous message-passing model). To
|
||||
invoke a system call, the client provides two identifiers to the
|
||||
system call dispatcher. The first identifies the server domain and
|
||||
the second identifies the system call to be invoked. The protection
|
||||
domain implementation should associate allowable system calls with
|
||||
particular server protection domains and reject any system call
|
||||
requests that are not within that set of allowable system calls. The
|
||||
system call implementations do not restrict the clients that are
|
||||
permitted to invoke each system call. No modifications that the
|
||||
client can make to the server domain and system call identifiers can
|
||||
open up new entrypoints into the server domain. The entrypoints are
|
||||
fixed at boot time.
|
||||
|
||||
However, if the identifiers were stored in shared memory, it may be
|
||||
possible for a protection domain to influence the system calls issued
|
||||
by some other protection domain, which may be undesirable. Thus, the
|
||||
server domain identifiers are stored in memory that can only be
|
||||
written by the kernel protection domain and the system call
|
||||
identifiers are embedded in the code.
|
||||
|
||||
The system call dispatcher is responsible for reconfiguring the system
|
||||
to enforce the appropriate resource access controls for the server
|
||||
protection domain. It should then transfer control to the approved
|
||||
entrypoint for the requested system call.
|
||||
|
||||
Contiki defines a process concept that is orthogonal to protection
|
||||
domains [2]. A single Contiki process may run code in multiple
|
||||
protection domains at various points in time. Contiki processes run
|
||||
in a cooperative scheduling context. Contiki also defines a
|
||||
preemptive scheduling context for interrupt handlers and real-time
|
||||
timers. When protection domain support is enabled, interrupts are
|
||||
only enabled when the application protection domain is active and is
|
||||
running code in the cooperative scheduling context. Code running in
|
||||
the preemptive context may also invoke multiple protection domains.
|
||||
Contiki can also support preemptive multithreading, but support for
|
||||
that has not yet been added to the X86 port so we do not discuss it
|
||||
further.
|
||||
|
||||
A single stack is shared by all code that runs in the cooperative
|
||||
scheduling context in all protection domains, and separate stacks are
|
||||
defined for short interrupt dispatchers in the preemptive scheduling
|
||||
context and for exception handlers and software system call
|
||||
dispatchers. Except for the interrupt dispatchers, code in the
|
||||
preemptive scheduling context also shares the same stack with the
|
||||
cooperative scheduling context. All protection domains also share a
|
||||
main data section, so similar considerations are also relevant to
|
||||
that.
|
||||
|
||||
Introducing multi-core support would complicate things further, since
|
||||
another core running a protection domain that the first core never
|
||||
invoked could access data from the protection domain on the first
|
||||
core. It may be possible to adequately address such concerns by
|
||||
allocating per-core stacks.
|
||||
|
||||
Note that this stack arrangement means that a given protection domain
|
||||
may read and write data written to the stack by some other protection
|
||||
domain. For example, a protection domain B may push data onto the
|
||||
stack and later pop that data off of the stack, but a protection
|
||||
domain A that invoked protection domain B may still be able to read
|
||||
the data that was pushed and popped to and from the stack, since
|
||||
popping the data off of the stack does not automatically erase that
|
||||
stack memory location. Another possibility is that protection domain
|
||||
B may modify a stack entry pushed by protection domain A before it
|
||||
invoked protection domain B, and protection domain A may later use the
|
||||
modified value. Permitting legitimate accesses to callers' stacks is
|
||||
in fact the primary motivation for this stack arrangement, in that it
|
||||
makes it simple for A to pass data to and from B (on the shared stack)
|
||||
when requesting services from B. A system call invocation is nearly
|
||||
transparent to the developer, appearing almost identical to an
|
||||
ordinary function call. However, B can access any data on the stack.
|
||||
The third case is that A can read data placed on the stack by B after
|
||||
B returns, unless B wipes that data from the stack before returning.
|
||||
A related sub-case is that if an interrupt handler is invoked, it
|
||||
pushes the current contents of the general-purpose registers onto the
|
||||
stack, which may then be revealed to other protection domains besides
|
||||
the one that was interrupted. However, interrupts are only actually
|
||||
enabled in the application protection domain.
|
||||
|
||||
Similarly, register contents may be accessed and modified across
|
||||
protection domain boundaries in some protection domain
|
||||
implementations. The TSS task switching mechanism automatically saves
|
||||
and restores many registers to and from TSS data structures when
|
||||
switching tasks, but the other protection domain implementations do
|
||||
not perform analogous operations.
|
||||
|
||||
For the reasons described above, each protection domain should only
|
||||
invoke other protection domains that it trusts to properly handle data
|
||||
on the stack.
|
||||
|
||||
Design
|
||||
------
|
||||
|
||||
### Boot Process
|
||||
|
||||
The system boots in the following phases.
|
||||
|
||||
#### UEFI Bootstrap
|
||||
|
||||
Primary implementation sources:
|
||||
|
||||
- cpu/x86/uefi/bootstrap_uefi.c
|
||||
|
||||
When the OS is compiled as a UEFI binary, a short bootstrap phase that
|
||||
is UEFI-compliant is run initially. It simply performs a minimal set
|
||||
of functions to exit the UEFI boot services and then transfer control
|
||||
to the Multiboot bootstrap phase.
|
||||
|
||||
#### Multiboot Bootstrap
|
||||
|
||||
Primary implementation sources:
|
||||
|
||||
- cpu/x86/bootstrap_quarkX1000.S
|
||||
|
||||
This phase disables interrupts, sets the stack pointer to the top of
|
||||
the main stack, and then invokes boot stage 0.
|
||||
|
||||
#### Boot Stage 0
|
||||
|
||||
Primary implementation sources:
|
||||
|
||||
- cpu/x86/init/common/cpu.c
|
||||
- cpu/x86/init/common/gdt.c
|
||||
|
||||
The UEFI firmware or Multiboot-compliant bootloader should have
|
||||
configured an initial Global Descriptor Table (GDT) with flat segments
|
||||
and configured the CPU to operate in protected mode with paging
|
||||
disabled. Flat segments each map the whole 4GiB physical memory
|
||||
space. This is the state of the system when the OS enters boot stage
|
||||
0. This stage is responsible for setting up a new GDT and loading the
|
||||
segment registers with the appropriate descriptors from the new GDT to
|
||||
enable boot stage 1 to run. Code in stage 1 for multi-segment
|
||||
protection domain implementations require that the appropriate
|
||||
segment-based address translations be configured.
|
||||
|
||||
#### Boot Stage 1
|
||||
|
||||
Primary implementation sources:
|
||||
|
||||
- cpu/x86/init/common/cpu.c
|
||||
- cpu/x86/init/common/idt.c
|
||||
- cpu/x86/mm/prot-domains.c
|
||||
|
||||
Boot stage 1 intializes the Interrupt Descriptor Table (IDT) and
|
||||
installs a handler for double-fault exceptions. Handlers for
|
||||
additional interrupts and exceptions are installed later in boot
|
||||
stages 1 and 2.
|
||||
|
||||
This stage also initializes protection domain support and enters the
|
||||
kernel protection domain.
|
||||
|
||||
#### Boot Stage 2
|
||||
|
||||
Primary implementation sources:
|
||||
|
||||
- cpu/x86/init/common/cpu.c
|
||||
- platform/galileo/contiki-main.c
|
||||
|
||||
The entrypoint for the kernel protection domain is 'main'. Boot stage
|
||||
2 initializes hardware devices and associated interrupts. It then
|
||||
transfers control to the application protection domain. Note that
|
||||
this is a transfer of control, not a call that would be matched with
|
||||
some future return. This is an important distinction, because
|
||||
protection domains are not reentrant. Thus, if the kernel protection
|
||||
domain called the application protection domain, it would not be
|
||||
possible to invoke any kernel system calls until the system is reset,
|
||||
since the application protection domain never exits/returns while the
|
||||
system is running. There are not actually any kernel system calls
|
||||
provided in the initial implementation of protection domains, but they
|
||||
may be added in the future.
|
||||
|
||||
The core protection domain configuration (e.g. allowable system calls
|
||||
and entrypoints, registered protection domains, etc.) is frozen by the
|
||||
conclusion of boot stage 2 to help prevent erroneous changes that
|
||||
could reduce the robustness of the system. The way that it is frozen
|
||||
is that there are no kernel system calls that are intended to permit
|
||||
changes to the core protection domain configuration. Thus, once the
|
||||
kernel protection domain has exited, the only way the core protection
|
||||
domain configuration can change would be due to undesirable memory
|
||||
manipulations (e.g. due to a faulty device driver).
|
||||
|
||||
#### Boot Stage 3
|
||||
|
||||
Primary implementation sources:
|
||||
|
||||
- platform/galileo/contiki-main.c
|
||||
|
||||
Boot stage 3 performs initialization procedures that are less
|
||||
tightly-coupled to hardware. For example, it launches Contiki
|
||||
processes and invokes Contiki configuration routines.
|
||||
|
||||
### Privilege Levels
|
||||
|
||||
When protection domain support is inactive, all code runs at
|
||||
ring/privilege level 0. When protection domain support is active,
|
||||
only exception handlers and system call dispatchers (including
|
||||
dispatchers for system call returns) run at ring level 0. Code in the
|
||||
preemptive scheduling context runs at ring level 2 and code in the
|
||||
cooperative scheduling context runs at ring level 3. Ring levels with
|
||||
higher numbers are less privileged than those with lower numbers.
|
||||
Ring level 1 is unused.
|
||||
|
||||
### IO and Interrupt Privileges
|
||||
|
||||
The kernel protection domain cooperative scheduling context needs
|
||||
access to IO ports, for device initialization. Some other protection
|
||||
domains also require such access. The IO Privilege Level (IOPL) that
|
||||
is assigned to a protection domain using the relevant bits in the
|
||||
EFLAGS field could be set according to whether IO port access is
|
||||
required in that protection domain. This is straightforward for TSS,
|
||||
which includes separate flags settings for each protection domain.
|
||||
However, this would introduce additional complexity and overhead in
|
||||
the critical system call and return dispatchers for other plugins.
|
||||
Instead, the IOPL is always set to block IO access from the
|
||||
cooperative scheduling context. Port IO instructions in that context
|
||||
will then generate general protection faults, and the exception
|
||||
handler decodes and emulates authorized port IO instructions.
|
||||
|
||||
Interrupts are handled at ring level 2, since they do not use any
|
||||
privileged instructions. They do cause the interrupt flag to be
|
||||
cleared as they are delivered. The interrupt flag can only be
|
||||
modified by instructions executing at a ring level that is numerically
|
||||
less than or equal to the IOPL. Each interrupt handler needs to set
|
||||
the interrupt flag using the IRET instruction when it returns.
|
||||
Protection domains that require access to port IO (currently just the
|
||||
kernel protection domain) are configured with an IOPL of 3 whereas
|
||||
others are configured with an IOPL of 2. That is why interrupts are
|
||||
configured to run at ring level 2. Interrupts are only enabled in the
|
||||
application protection domain.
|
||||
|
||||
Some interrupt handlers require access to port IO, and all are
|
||||
permitted such access, since they need it anyway for restoring the
|
||||
interrupt flag when returning. IO port access is a very powerful
|
||||
privilege, since it can be used to remap MMIO regions of PCI devices,
|
||||
reconfigure PCI devices, etc. Thus, further restricting access to IO
|
||||
ports may improve the robustness of the system, but would increase
|
||||
complexity and space requirements and possibly necessitate additional
|
||||
context switches, since IO port access is controlled by the combined
|
||||
settings of IOPL as well as an optional IO bitmap in the TSS.
|
||||
|
||||
### Interrupt and Exception Dispatching
|
||||
|
||||
Primary implementation sources:
|
||||
- cpu/x86/init/common/interrupt.h
|
||||
|
||||
Separate stacks are allocated for dispatching interrupts and
|
||||
exceptions. However, to save space, the main bodies of some interrupt
|
||||
and exception handlers are run on the main stack. A handler may
|
||||
expect to have access to data from the interrupt or exception stack,
|
||||
so the interrupt or exception dispatcher copies that data prior to
|
||||
pivoting to the main stack and executing the handler.
|
||||
|
||||
### Protection Domain Control Structures (PDCSes)
|
||||
|
||||
Each protection domain is managed by the kernel and privileged
|
||||
functions using a PDCS. The structure of the PDCS is partially
|
||||
hardware-imposed in the cases of the two segment-based plugins, since
|
||||
the PDCS contains the Local Descriptor Table (LDT) and the TSS, if
|
||||
applicable. In the paging plugin, the PDCS structure is entirely
|
||||
software-defined. None of the initial protection domain plugins
|
||||
support re-entrant protection domains due to hardware-imposed
|
||||
limitations of TSS and to simplify the implementation of the other
|
||||
plugins by enabling domain-specific information (e.g. system call
|
||||
return address) to be trivially stored in each PDCS.
|
||||
|
||||
### Paging-Based Protection Domains
|
||||
|
||||
Primary implementation sources:
|
||||
|
||||
- cpu/x86/mm/paging-prot-domains.c
|
||||
- cpu/x86/mm/syscalls-int.c
|
||||
- cpu/x86/mm/syscalls-int-asm.S
|
||||
|
||||
#### Introduction
|
||||
|
||||
Only a single page table is used for all protection domains. A flat
|
||||
memory model is used. Almost all linear-to-physical address mappings
|
||||
are identity mappings, with the exceptions being the MMIO and metadata
|
||||
regions. The X86 port of Contiki currently only supports at most one
|
||||
MMIO and one metadata range per driver, and the paging-based
|
||||
protection domain implementation always starts at particular linear
|
||||
addresses when mapping an MMIO or metadata range. This may reduce
|
||||
overhead, due to the way protection domain switches are implemented.
|
||||
|
||||
#### System Call and Return Dispatching
|
||||
|
||||
The system call dispatcher executes at ring level 0, since it uses the
|
||||
privileged INVLPG or MOV CR3 instructions to invalidate TLB entries.
|
||||
The dispatcher modifies page table entries to grant only the
|
||||
permissions required by the protection domain being activated. It
|
||||
then optionally uses the INVLPG instruction to invalidate any TLB
|
||||
entries for any page table entries that were modified. If INVLPG is
|
||||
not used to invalidate specific TLB entries, then CR3 is reloaded to
|
||||
invalidate the entire TLB (global entries would be excluded, but they
|
||||
are not used in this implementation).
|
||||
|
||||
It is more efficient to always start at a particular linear address
|
||||
when mapping an MMIO or metadata region, since the page table entries
|
||||
for that region can be updated to unmap any previous region of that
|
||||
type, map the new region, and then invalidated to cause the new
|
||||
settings to take effect. The alternative using an identity
|
||||
linear-to-physical address mapping for regions would be to unmap the
|
||||
previous region by editing one set of page table entries and to then
|
||||
map the new region by editing a different set of page table entries
|
||||
and to finally perform invalidations for both sets of page table
|
||||
entries. Another drawback of such an identity address mapping is that
|
||||
additional page tables may need to be allocated to represent the
|
||||
various MMIO regions, since page tables are indexed by linear address
|
||||
and MMIO regions are often at high physical addresses. Note that this
|
||||
is specific to MMIO regions, since metadata regions are not at
|
||||
particularly high physical addresses. Additionally, if different base
|
||||
linear addresses are used, it is necessary to communicate those to the
|
||||
system call handler code so that the regions can be accessed. This
|
||||
would require care to prevent an adversary from manipulating the
|
||||
addresses and it may increase complexity.
|
||||
|
||||
The overall process of handling a system call can be illustrated at a
|
||||
high level as follows. Some minor steps are omitted in the interest
|
||||
of clarity and brevity.
|
||||
|
||||
```
|
||||
== BEGIN Client protection domain ==========================================
|
||||
-- BEGIN Caller ------------------------------------------------------------
|
||||
1. Call system call stub.
|
||||
--
|
||||
20. Continue execution...
|
||||
-- END Caller --------------------------------------------------------------
|
||||
-- BEGIN System call stub --------------------------------------------------
|
||||
2. Already in desired (server) protection domain?
|
||||
- No: Issue software interrupt #100 to request system call.
|
||||
- Yes: Jump to system call body.
|
||||
-- END System call stub ----------------------------------------------------
|
||||
== END Client protection domain ============================================
|
||||
== BEGIN Ring level 0 ======================================================
|
||||
-- BEGIN System call dispatcher---------------------------------------------
|
||||
3. Check that the requested system call is allowed. Get entrypoint.
|
||||
4. Check that the server protection domain is available (not yet present
|
||||
in the protection domain call stack) and then mark it as busy.
|
||||
5. Save the caller return address from the main stack into the client
|
||||
PDCS.
|
||||
6. Overwrite the caller return address on the main stack to point to
|
||||
system call return stub.
|
||||
7. Push server protection domain onto protection domain call stack.
|
||||
8. Update the interrupt return stack EIP to start of system call body.
|
||||
9. Update and invalidate page table entries to grant only the permissions
|
||||
required by the server protection domain.
|
||||
10. Update interrupt flag to disable interrupts, since interrupts are only
|
||||
enabled in app protection domain, which exports no system calls.
|
||||
11. Perform interrupt return (IRET).
|
||||
-- END System call dispatcher ----------------------------------------------
|
||||
-- BEGIN System call return dispatcher -------------------------------------
|
||||
15. Mark protection domain on top of protection domain call stack as
|
||||
available.
|
||||
16. Retrieve the caller return address from the kernel data structure for
|
||||
the client protection domain and use it to overwrite the EIP in the
|
||||
interrupt return stack.
|
||||
17. Update and invalidate page table entries to grant only the permissions
|
||||
required by the client protection domain.
|
||||
18. Update interrupt flag to only enable interrupts if returning to app
|
||||
protection domain cooperative scheduling context.
|
||||
19. Perform interrupt return (IRET).
|
||||
-- END System call dispatcher ----------------------------------------------
|
||||
== END Ring level 0 ========================================================
|
||||
== BEGIN Server protection domain ==========================================
|
||||
-- BEGIN System call body --------------------------------------------------
|
||||
12. Execute the work for the requested system call.
|
||||
13. Return (to system call return stub, unless invoked from server
|
||||
protection domain, in which case return is to caller).
|
||||
-- END System call body ----------------------------------------------------
|
||||
-- BEGIN System call return stub -------------------------------------------
|
||||
14. Issue software interrupt #101 to request system call return.
|
||||
-- END System call return stub ---------------------------------------------
|
||||
== END Server protection domain ============================================
|
||||
```
|
||||
|
||||
The first step in performing a system call is to invoke a system call
|
||||
stub that actually issues the software interrupt to request a system
|
||||
call dispatch. This approach reduces disruption to existing code,
|
||||
since macros are used to generate separate stubs and corresponding
|
||||
system call bodies with a single system call signature definition.
|
||||
|
||||
#### Memory Layout
|
||||
|
||||
The approximate memory layout of the system is depicted below,
|
||||
starting with the highest physical addresses and proceeding to lower
|
||||
physical addresses. Optional permissions are denoted with
|
||||
parentheses. See cpu/x86/quarkX1000_paging.ld for details of how this
|
||||
memory layout is implemented.
|
||||
|
||||
```
|
||||
| Kernel | App | Other |
|
||||
... +--------+--------+--------+
|
||||
+------------------------------------------+ | | | |
|
||||
| Domain X MMIO | | | | (RW) |
|
||||
+------------------------------------------+ | | | |
|
||||
... | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Domain X DMA-accessible metadata | | | | (RW) |
|
||||
| (section .dma_bss) | | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Domain X metadata (section .meta_bss) | | | | (RW) |
|
||||
+------------------------------------------+ | | | |
|
||||
... | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Kernel-private data | | RW | | |
|
||||
| (sections .prot_dom_bss, .gdt_bss, etc.) | | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| System call data (section .syscall_bss) | | RW | R | R |
|
||||
+------------------------------------------+ | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Kernel-owned data (section .kern_bss) | | RW | R | R |
|
||||
+------------------------------------------+ | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Page-aligned, Kernel-owned data | | RW | R | R |
|
||||
| (section .page_aligned_kern_bss) | | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Common data | | RW | RW | RW |
|
||||
| (sections .data, .rodata*, .bss, etc.) | | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
(not-present guard band page) | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Exception stack | | RW | RW | RW |
|
||||
| (section .exc_stack) | | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Interrupt stack | | RW | RW | RW |
|
||||
| (section .int_stack) | | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Main stack (section .main_stack) | | RW | RW | RW |
|
||||
+------------------------------------------+ | | | |
|
||||
(not-present guard band page) | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Main code (.text) | | RX | RX | RX |
|
||||
+------------------------------------------+ | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Bootstrap code (section .boot_text) | | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
| Multiboot header | | | | |
|
||||
+------------------------------------------+ | | | |
|
||||
...
|
||||
```
|
||||
|
||||
The only protection domain that is permitted to access kernel-owned
|
||||
data is the kernel protection domain. Some devices can also be
|
||||
instructed to perform DMA to kernel-owned data, although that is an
|
||||
incorrect configuration.
|
||||
|
||||
Paging only differentiates between memory accesses from ring 3 (user
|
||||
level) and those from rings 0-2 (supervisor level). To avoid granting
|
||||
code running in the preemptive scheduling context supervisory write
|
||||
access to kernel data structures (including the page tables), those
|
||||
structures are marked read-only (except when the kernel protection
|
||||
domain is active) and the Write Protect (WP) bit in Control Register 0
|
||||
(CR0) is cleared only when it is necessary to update a write-protected
|
||||
structure. Only ring 0 is allowed to modify CR0.
|
||||
|
||||
Optional metadata for each protection domain is intended to only be
|
||||
accessible from the associated protection domain and devices.
|
||||
|
||||
Read accesses to executable code have not been observed to be needed
|
||||
in at least a limited set of tests, but they are permitted, since
|
||||
paging does not support an execute-only permission setting. On the
|
||||
other hand, the Execute-Disable feature is used to prevent execution
|
||||
of non-code memory regions. All non-startup code is mapped in all
|
||||
protection domains. Limiting the code that is executable within each
|
||||
protection domain to just the code that is actually needed within that
|
||||
protection domain could improve the robustness of the system, but it
|
||||
is challenging to determine all code that may be needed in a given
|
||||
protection domain (e.g. all needed library routines).
|
||||
|
||||
Stack accesses to non-stack memory are not needed, but they are
|
||||
permitted. However, one page of unmapped linear address space is
|
||||
placed above and below the stacks to detect erroneous stack accesses
|
||||
to those linear address regions, which are the types of accesses most
|
||||
likely to occur during a stack overflow or underflow condition. The
|
||||
main stack is placed just below the interrupt stack, which is just
|
||||
below the exception stack. Stack overflows are more common than stack
|
||||
underflows, which motivates arranging the stacks such that an overflow
|
||||
from a less-critical stack will not affect a more-critical stack.
|
||||
Furthermore, the main stack is the most likely to overflow, since the
|
||||
code that uses it is typically the most voluminous and difficult to
|
||||
characterize. That provides additional motivation for positioning it
|
||||
such that an overflow results in an immediate page fault. An
|
||||
alternative design placing each stack on a separate group of
|
||||
contiguous pages may improve the robustness of the system by
|
||||
permitting the insertion of unmapped guard pages around them to
|
||||
generate page faults in the event an overflow or underflow occurs on
|
||||
any stack. However, that would consume additional memory.
|
||||
|
||||
Data in the .rodata sections is marked read/write, even though it may
|
||||
be possible to improve the robustness of the system by marking that
|
||||
data as read-only. Doing so would introduce additional complexity
|
||||
into the system.
|
||||
|
||||
### Hardware-Switched Segment-Based Protection Domains
|
||||
|
||||
Primary implementation sources:
|
||||
|
||||
- cpu/x86/mm/tss-prot-domains.c
|
||||
- cpu/x86/mm/tss-prot-domains-asm.S
|
||||
|
||||
#### Introduction
|
||||
|
||||
One TSS is allocated for each protection domain. Each one is
|
||||
associated with its own dedicated LDT. The memory resources assigned
|
||||
to each protection domain are represented as segment descriptors in
|
||||
the LDT for the protection domain. Additional shared memory resources
|
||||
are represented as segment descriptors in the GDT.
|
||||
|
||||
#### System Call and Return Dispatching
|
||||
|
||||
The system call dispatcher runs in the context of the server
|
||||
protection domain. It is a common piece of code that is shared among
|
||||
all protection domains. Thus, each TSS, except the application TSS,
|
||||
has its EIP field initialized to the entrypoint for the system call
|
||||
dispatcher so that will be the first code to run when the first switch
|
||||
to that task is performed.
|
||||
|
||||
The overall process of handling a system call can be illustrated at a
|
||||
high level as follows. Some minor steps are omitted from this
|
||||
illustration in the interest of clarity and brevity.
|
||||
|
||||
```
|
||||
== BEGIN Client protection domain ==========================================
|
||||
-- BEGIN Caller ------------------------------------------------------------
|
||||
1. Call system call stub.
|
||||
--
|
||||
13. Continue execution...
|
||||
-- END Caller --------------------------------------------------------------
|
||||
-- BEGIN System call stub --------------------------------------------------
|
||||
2. Already in desired (server) protection domain?
|
||||
- No: Request task switch to server protection domain.
|
||||
- Yes: Jump to system call body.
|
||||
--
|
||||
12. Return to caller.
|
||||
-- END System call stub ----------------------------------------------------
|
||||
== END Client protection domain ============================================
|
||||
== BEGIN Server protection domain ==========================================
|
||||
-- BEGIN System call dispatcher---------------------------------------------
|
||||
3. Check that the requested system call is allowed. Get entrypoint.
|
||||
4. Switch to the main stack.
|
||||
5. Pop the client return address off the stack to a callee-saved register.
|
||||
6. Push the address of the system call return dispatcher onto the stack.
|
||||
7. Jump to system call body.
|
||||
--
|
||||
10. Restore the client return address to the stack.
|
||||
11. Request task switch to client protection domain.
|
||||
-- END System call dispatcher ----------------------------------------------
|
||||
-- BEGIN System call body --------------------------------------------------
|
||||
8. Execute the work for the requested system call.
|
||||
9. Return (to system call return stub, unless invoked from server
|
||||
protection domain, in which case return is to caller).
|
||||
-- END System call body ----------------------------------------------------
|
||||
== END Server protection domain ============================================
|
||||
```
|
||||
|
||||
An additional exception handler is needed, for the "Device Not
|
||||
Available" exception. The handler comprises just a CLTS and an IRET
|
||||
instruction. The CLTS instruction is privileged, which is why it must
|
||||
be run at ring level 0. This exception handler is invoked when a
|
||||
floating point instruction is used following a task switch, and its
|
||||
sole purpose is to enable the floating point instruction to execute
|
||||
after the exception handler returns. See the TSS resources listed
|
||||
above for more details regarding interactions between task switching
|
||||
and floating point instructions.
|
||||
|
||||
Each segment register may represent a different data region within
|
||||
each protection domain, although the FS register is used for two
|
||||
separate purposes at different times. The segments are defined as
|
||||
follows:
|
||||
|
||||
- CS (code segment) maps all non-startup code with execute-only
|
||||
permissions in all protection domains. Limiting the code that is
|
||||
executable within each protection domain to just the code that is
|
||||
actually needed within that protection domain could improve the
|
||||
robustness of the system, but it is challenging to determine all
|
||||
code that may be needed in a given protection domain (e.g. all
|
||||
needed library routines). Furthermore, that code may not all be
|
||||
contiguous, and each segment descriptor can only map a contiguous
|
||||
memory region. Finally, segment-based memory addressing is
|
||||
relative to an offset of zero from the beginning of each segment,
|
||||
introducing additional complexity if such fine-grained memory
|
||||
management were to be used.
|
||||
- DS (default data segment) typically maps the main stack and all
|
||||
non-stack data memory that is accessible from all protection
|
||||
domains. Limiting the data that is accessible via DS within each
|
||||
protection domain to just the subset of the data that is actually
|
||||
needed within that protection domain could improve the robustness
|
||||
of the system, but it is challenging for similar reasons to those
|
||||
that apply to CS. Access to the main stack via DS is supported so
|
||||
that code that copies the stack pointer to a register and attempts
|
||||
to access stack entries via DS works correctly. Disallowing access
|
||||
to the main stack via DS could improve the robustness of the
|
||||
system, but that may require modifying code that expects to be able
|
||||
to access the stack via DS.
|
||||
- ES is loaded with the same segment descriptor as DS so that string
|
||||
operations (e.g. the MOVS instruction) work correctly.
|
||||
- FS usually maps the kernel-owned data region. That region can only
|
||||
be written via FS in the kernel protection domain. FS contains a
|
||||
descriptor specifying a read-only mapping in all other protection
|
||||
domains except the application protection domain, in which FS is
|
||||
nullified. Requiring that code specifically request access to the
|
||||
kernel-owned data region by using the FS segment may improve the
|
||||
robustness of the system by blocking undesired accesses to the
|
||||
kernel-owned data region via memory access instructions within the
|
||||
kernel protection domain that implicitly access DS. The reason for
|
||||
granting read-only access to the kernel-owned data region from most
|
||||
protection domains is that the system call dispatcher runs in the
|
||||
context of the server protection domain to minimize overhead, and
|
||||
it requires access to the kernel-owned data region. It may improve
|
||||
the robustness of the system to avoid this by running the system
|
||||
call dispatcher in a more-privileged ring level (e.g. ring 1)
|
||||
within the protection domain and just granting access to the
|
||||
kernel-owned data region from that ring. However, that would
|
||||
necessitate a ring level transition to ring 3 when dispatching the
|
||||
system call, which would increase overhead. The application
|
||||
protection domain does not export any system calls, so it does not
|
||||
require access to the kernel-owned data region.
|
||||
- FS is temporarily loaded with a segment descriptor that maps just
|
||||
an MMIO region used by a driver protection domain when such a
|
||||
driver needs to perform MMIO accesses.
|
||||
- GS maps an optional region of readable and writable metadata that
|
||||
can be associated with a protection domain. In protection domains
|
||||
that are not associated with metadata, GS is nullified.
|
||||
- SS usually maps just the main stack. This may improve the
|
||||
robustness of the system by enabling immediate detection of stack
|
||||
underflows and overflows rather than allowing such a condition to
|
||||
result in silent data corruption. Interrupt handlers use a stack
|
||||
segment that covers the main stack and also includes a region above
|
||||
the main stack that is specifically for use by interrupt handlers.
|
||||
In like manner, exception handlers use a stack segment that covers
|
||||
both of the other stacks and includes an additional region. This
|
||||
is to support the interrupt dispatchers that copy parameters from
|
||||
the interrupt-specific stack region to the main stack prior to
|
||||
pivoting to the main stack to execute an interrupt handler body.
|
||||
|
||||
The approximate memory layout of the system is depicted below,
|
||||
starting with the highest physical addresses and proceeding to lower
|
||||
physical addresses. The memory ranges that are mapped at various
|
||||
times by each of the segment registers are also depicted. Read the
|
||||
descriptions of each segment above for more information about what
|
||||
memory range may be mapped by each segment register at various times
|
||||
with various protection domain configurations. Parenthetical notes
|
||||
indicate the protection domains that can use each mapping. The suffix
|
||||
[L] indicates that the descriptor is loaded from LDT. Optional
|
||||
mappings are denoted by a '?' after the protection domain label. The
|
||||
'other' protection domain label refers to protection domains other
|
||||
than the application and kernel domains.
|
||||
|
||||
```
|
||||
...
|
||||
+------------------------------------------+ \
|
||||
| Domain X MMIO | +- FS[L]
|
||||
+------------------------------------------+ / (other?)
|
||||
...
|
||||
+------------------------------------------+ \
|
||||
| Domain X DMA-accessible metadata | +- GS[L] (other?)
|
||||
| (section .dma_bss) | |
|
||||
+------------------------------------------+ /
|
||||
+------------------------------------------+ \
|
||||
| Domain X metadata (section .meta_bss) | +- GS[L] (other?)
|
||||
+------------------------------------------+ /
|
||||
...
|
||||
+------------------------------------------+ \
|
||||
| Kernel-private data | |
|
||||
| (sections .prot_dom_bss, .gdt_bss, etc.) | +- FS[L] (kern)
|
||||
+------------------------------------------+ |
|
||||
+------------------------------------------+ \
|
||||
| System call data (section .syscall_bss) | |
|
||||
+------------------------------------------+ +- FS[L] (all)
|
||||
+------------------------------------------+ |
|
||||
| Kernel-owned data (section .kern_bss) | |
|
||||
+------------------------------------------+ /
|
||||
+------------------------------------------+ \
|
||||
| Common data | |
|
||||
| (sections .data, .rodata*, .bss, etc.) | |
|
||||
+------------------------------------------+ +- DS, ES
|
||||
+------------------------------------------+ \ | (all)
|
||||
| Exception stack (section .exc_stack) | | |
|
||||
|+----------------------------------------+| \ |
|
||||
|| Interrupt stack (section .int_stack) || | |
|
||||
||+--------------------------------------+|| \ |
|
||||
||| Main stack (section .main_stack) ||| +- SS (all) |
|
||||
+++--------------------------------------+++ / /
|
||||
+------------------------------------------+ \
|
||||
| Main code (.text) | +- CS (all)
|
||||
+------------------------------------------+ /
|
||||
+------------------------------------------+
|
||||
| Bootstrap code (section .boot_text) |
|
||||
+------------------------------------------+
|
||||
+------------------------------------------+
|
||||
| Multiboot header |
|
||||
+------------------------------------------+
|
||||
...
|
||||
```
|
||||
|
||||
This memory layout is more efficient than the layout that is possible
|
||||
with paging-based protection domains, since segments have byte
|
||||
granularity, whereas the minimum unit of control supported by paging
|
||||
is a 4KiB page. For example, this means that metadata may need to be
|
||||
padded to be a multiple of the page size. This may also permit
|
||||
potentially-undesirable accesses to padded areas of code and data
|
||||
regions that do not entirely fill the pages that they occupy.
|
||||
|
||||
Kernel data structure access, including to the descriptor tables
|
||||
themselves, is normally restricted to the code running at ring level
|
||||
0, specifically the exception handlers and the system call and return
|
||||
dispatchers. It is also accessible from the cooperative scheduling
|
||||
context in the kernel protection domain. Interrupt delivery is
|
||||
disabled in the kernel protection domain, so the preemptive scheduling
|
||||
context is not used.
|
||||
|
||||
SS, DS, and ES all have the same base address, since the compiler may
|
||||
assume that a flat memory model is in use. Memory accesses that use a
|
||||
base register of SP/ESP or BP/EBP or that are generated by certain
|
||||
other instructions (e.g. PUSH, RET, etc.) are directed to SS by
|
||||
default, whereas other accesses are directed to DS or ES by default.
|
||||
The compiler may use an instruction that directs an access to DS or ES
|
||||
even if the data being accessed is on the stack, which is why these
|
||||
three segments must use the same base address. However, it is
|
||||
possible to use a lower limit for SS than for DS and ES for the
|
||||
following reasons. Compilers commonly provide an option for
|
||||
preventing the frame pointer, EBP, from being omitted and possibly
|
||||
used to point to non-stack data. In our tests, compilers never used
|
||||
ESP to point to non-stack data.
|
||||
|
||||
Each task switch ends up saving and restoring more state than is
|
||||
actually useful to us, but the implementation attempts to minimize
|
||||
overhead by configuring the register values in each TSS to reduce the
|
||||
number of register loads that are needed in the system call
|
||||
dispatcher. Specifically, two callee-saved registers are populated
|
||||
with base addresses used when computing addresses in the entrypoint
|
||||
information table as well as a mask corresponding to the ID of the
|
||||
server protection domain that is used to check whether the requested
|
||||
system call is exported by the server protection domain. Callee-saved
|
||||
registers are used, since the task return will update the saved
|
||||
register values.
|
||||
|
||||
Note that this implies that the intervening code run between the task
|
||||
call and return can modify critical data used by the system call
|
||||
dispatcher. However, this is analogous to the considerations
|
||||
associated with sharing a single stack amongst all protection domains
|
||||
and should be addressed similarly, by only invoking protection domains
|
||||
that are trusted by the caller to not modify the saved critical
|
||||
values. This consideration is specific to the TSS-based dispatcher
|
||||
and is not shared by the ring 0 dispatcher used in the other
|
||||
plugins.
|
||||
|
||||
Data in the .rodata sections is marked read/write, even though it may
|
||||
be possible to improve the robustness of the system by marking that
|
||||
data as read-only. Doing so would introduce even more complexity into
|
||||
the system than would be the case with paging-based protection
|
||||
domains, since it would require allocating different segment
|
||||
descriptors for the read-only vs. the read/write data.
|
||||
|
||||
#### Supporting Null-Pointer Checks
|
||||
|
||||
A lot of code considers a pointer value of 0 to be invalid. However,
|
||||
segment offsets always start at 0. To accommodate the common software
|
||||
behavior, at least the first byte of each segment is marked as
|
||||
unusable. An exception to this is that the first byte of the stack
|
||||
segments is usable.
|
||||
|
||||
#### Interrupt and Exception Dispatching
|
||||
|
||||
A distinctive challenge that occurs during interrupt and exception
|
||||
dispatching is that the state of the segment registers when an
|
||||
interrupt or exception occurs is somewhat unpredictable. For example,
|
||||
an exception may occur while MMIO is being performed, meaning that FS
|
||||
is loaded with the MMIO descriptor instead of the kernel descriptor.
|
||||
Leaving the segment registers configured in that way could cause
|
||||
incorrect interrupt or exception handler behavior. Thus, the
|
||||
interrupt or exception dispatcher must save the current segment
|
||||
configuration, switch to a configuration that is suitable for the
|
||||
handler body, and then restore the saved segment configuration after
|
||||
the handler body returns. Another motivation for this is that the
|
||||
interrupted code may have corrupted the segment register configuration
|
||||
in an unexpected manner, since segment register load instructions are
|
||||
unprivileged. Similar segment register updates must be performed for
|
||||
similar reasons when dispatching system calls.
|
||||
|
||||
### Software-Switched Segment-Based Protection Domains
|
||||
|
||||
Primary implementation sources:
|
||||
|
||||
- cpu/x86/mm/swseg-prot-domains.c
|
||||
|
||||
The requirement to allocate a TSS for each protection domain in the
|
||||
hardware-switched segments plugin may consume a substantial amount of
|
||||
space, since the size of each TSS is fixed by hardware to be at least
|
||||
104 bytes. The software-switched segments plugin saves space by
|
||||
defining a more compact PDCS. However, the layout and definitions of
|
||||
the segments is identical to what was described above for the
|
||||
hardware-switched segments plugin.
|
||||
|
||||
The system call and return procedure is mostly identical to that for
|
||||
paging-based protection domains. However, instead of updating and
|
||||
invalidating page tables, the dispatchers update the LDT and some of
|
||||
the segment registers.
|
||||
|
||||
### Pointer Validation
|
||||
|
||||
Primary implementation sources:
|
||||
- cpu/x86/mm/syscalls.h
|
||||
|
||||
At the beginning of each system call routine, it is necessary to check
|
||||
that any untrusted pointer that could have been influenced by a caller
|
||||
(i.e. a stack parameter or global variable) refers to a location above
|
||||
the return address and to halt otherwise. This is to prevent a
|
||||
protection domain from calling a different protection domain and
|
||||
passing a pointer that references a location in the callee's stack
|
||||
other than its parameters to influence the execution of the callee in
|
||||
an unintended manner. For example, if an incoming pointer referenced
|
||||
the return address, it could potentially redirect execution with the
|
||||
privileges of the callee protection domain.
|
||||
|
||||
When the paging-based plugin is in use, it is also necessary to check
|
||||
that the pointer is either within the stack region or the shared data
|
||||
region (or a guard band region, since that will generate a fault) to
|
||||
prevent redirection of data accesses to MMIO or metadata regions. The
|
||||
other plugins already configure segments to restrict accesses to DS to
|
||||
just those regions. Pointers provided as inputs to system calls as
|
||||
defined above should never be dereferenced in any segment other than
|
||||
DS.
|
||||
|
||||
The pointer is both validated and copied to a new storage location,
|
||||
which must be within the callee's local stack region (excluding the
|
||||
parameter region). This is to mitigate scenarios such as two pointers
|
||||
being validated and an adversary later inducing a write through one of
|
||||
the pointers to the other pointer to corrupt the latter pointer before
|
||||
it is used.
|
||||
|
||||
Any pointer whose value is fixed at link or load time does not need to
|
||||
be validated prior to use, since no adversary within the defined
|
||||
threat model is able to influence the link or load process.
|
||||
|
||||
### DMA Restrictions
|
||||
|
||||
Primary implementation sources:
|
||||
- cpu/x86/drivers/quarkX1000/imr.c
|
||||
- cpu/x86/drivers/quarkX1000/imr-conf.c
|
||||
|
||||
The CPU is not the only agent with the ability to issue requests to
|
||||
the interconnect within the SoC. For example, SoC peripherals such as
|
||||
the Ethernet driver use DMA to efficiently access memory buffers.
|
||||
This could introduce a risk that DMA could be used to bypass the
|
||||
memory protections enforced on the CPU by segmentation or paging. For
|
||||
example, a device driver could instruct a device to access a memory
|
||||
region to which the kernel has not granted the driver's protection
|
||||
domain permission to access.
|
||||
|
||||
The Isolated Memory Region (IMR) feature is configured to restrict the
|
||||
memory that can be accessed by system agents other than the CPU [3].
|
||||
It only allows those system agents to access portions of the Contiki
|
||||
memory space that are specifically intended to be used with DMA. The
|
||||
source code for each protection domain specifies that its optional
|
||||
metadata region needs to be accessible from other system agents
|
||||
besides the CPU by using ATTR_BSS_DMA instead of ATTR_BSS_META when
|
||||
allocating storage for the metadata.
|
||||
|
||||
Extending the Framework
|
||||
-----------------------
|
||||
|
||||
### Adding a New Protection Domain
|
||||
|
||||
The following steps are required. See the existing device drivers for
|
||||
examples of various types of protection domains and how they are
|
||||
initialized.
|
||||
|
||||
- Allocate storage for the PDCS and the corresponding
|
||||
client-accessible data structure using the PROT_DOMAINS_ALLOC
|
||||
macro.
|
||||
- Apply the ATTR_BSS_META attribute to the metadata structure, if
|
||||
applicable. Apply the ATTR_BSS_DMA attribute instead if the
|
||||
metadata structure needs to be DMA-accessible. Pad the metadata
|
||||
structure to completely fill an integer multiple of the minimum
|
||||
page size, 4096, when paging-based protection domains are in use.
|
||||
See the definition of quarkX1000_eth_meta_t for an example.
|
||||
- Perform the following steps during boot stage 2:
|
||||
- Initialize the protection domain ID in the client-accessible data
|
||||
structure using the PROT_DOMAINS_INIT_ID macro.
|
||||
- Register the domain. See prot-domains.c:prot_domains_init for an
|
||||
example of registering a non-driver protection domain. See
|
||||
cpu/x86/drivers/quarkX1000/eth.c:quarkX1000_eth_init for an
|
||||
example of registering a PCI driver protection domain with an
|
||||
MMIO region and a metadata region.
|
||||
|
||||
### Adding a New System Call
|
||||
|
||||
The following steps are required:
|
||||
|
||||
- Define the system call procedure using the SYSCALLS_DEFINE or
|
||||
SYSCALLS_DEFINE_SINGLETON macro. See
|
||||
cpu/x86/drivers/legacy_pc/uart-16x50.c:uart_16x50_tx for an example
|
||||
of a non-singleton system call. See
|
||||
cpu/x86/drivers/quarkX1000/eth.c:quarkX1000_eth_send for an example
|
||||
of a singleton system call. A singleton system call is one for
|
||||
which at most one server protection domain will be associated with
|
||||
it.
|
||||
- During boot phase 2, associate the system call with one or more
|
||||
server protection domains using the SYSCALLS_AUTHZ macro.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
To enable protection domain support, add "X86_CONF_PROT_DOMAINS=" to
|
||||
the command line and specify one of the following options:
|
||||
|
||||
- paging
|
||||
- tss
|
||||
- swseg
|
||||
|
||||
The paging option accepts a sub-option to determine whether the TLB is
|
||||
fully- or selectively-invalidated during protection domain switches.
|
||||
By default, full invalidation is selected. Set the
|
||||
X86_CONF_USE_INVLPG variable to 1 to override the default.
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
[1] J. H. Saltzer, "Protection and the Control of Information Sharing
|
||||
in Multics," Commun. ACM, vol. 17, no. 7, pp. 388-402, Jul. 1974.
|
||||
|
||||
[2] https://github.com/contiki-os/contiki/wiki/Processes
|
||||
|
||||
[3] "Intel(R) Quark(TM) SoC X1000 Secure Boot Programmer's Reference
|
||||
Manual,"
|
||||
http://www.intel.com/support/processors/quark/sb/CS-035228.htm
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_GDT_LAYOUT_H_
|
||||
#define CPU_X86_MM_GDT_LAYOUT_H_
|
||||
|
||||
#include "prot-domains.h"
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
|
||||
/**
|
||||
* Number of fixed GDT descriptors. Additional descriptors may be defined
|
||||
* outside of gdt.c.
|
||||
*/
|
||||
#define GDT_NUM_FIXED_DESC 7
|
||||
#elif X86_CONF_PROT_DOMAINS_MULTI_SEG
|
||||
#define GDT_NUM_FIXED_DESC 11
|
||||
#else
|
||||
#define GDT_NUM_FIXED_DESC 3
|
||||
#endif
|
||||
|
||||
#define GDT_IDX_NULL 0
|
||||
/**
|
||||
* Flat code segment, used at boot and also for the rest of the system's
|
||||
* runtime when protection domains are disabled
|
||||
*/
|
||||
#define GDT_IDX_CODE_FLAT 1
|
||||
/**
|
||||
* Flat data segment, used at boot and also for the rest of the system's
|
||||
* runtime when protection domains are disabled
|
||||
*/
|
||||
#define GDT_IDX_DATA_FLAT 2
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE
|
||||
/** Default (post-boot) code segment */
|
||||
#define GDT_IDX_CODE 3
|
||||
/**
|
||||
* Same bounds and permissions as default code segment, but at the interrupt
|
||||
* handler privilege level
|
||||
*/
|
||||
#define GDT_IDX_CODE_INT 4
|
||||
/** Stack segment for interrupt handlers */
|
||||
#define GDT_IDX_STK_INT 5
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
|
||||
#define GDT_IDX_CODE_EXC GDT_IDX_CODE_FLAT
|
||||
/** Default data segment used by code at all privilege levels */
|
||||
#define GDT_IDX_DATA 6
|
||||
#define GDT_IDX_STK GDT_IDX_DATA
|
||||
#define GDT_IDX_STK_EXC GDT_IDX_DATA_FLAT
|
||||
#else
|
||||
/**
|
||||
* Same bounds and permissions as default code segment, but at the exception
|
||||
* handler privilege level
|
||||
*/
|
||||
#define GDT_IDX_CODE_EXC 6
|
||||
/** R/W kernel data descriptor used during boot stage 1 */
|
||||
#define GDT_IDX_DATA_KERN_EXC 7
|
||||
/** Default data segment used by code at all privilege levels */
|
||||
#define GDT_IDX_DATA 8
|
||||
/**
|
||||
* Default stack segment, which overlaps with the beginning of the default data
|
||||
* segment
|
||||
*/
|
||||
#define GDT_IDX_STK 9
|
||||
/** Stack segment for exception handlers */
|
||||
#define GDT_IDX_STK_EXC 10
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS
|
||||
#define GDT_IDX_TSS(dom_id) (GDT_NUM_FIXED_DESC + (2 * (dom_id)))
|
||||
#define GDT_IDX_LDT(dom_id) (GDT_NUM_FIXED_DESC + (2 * (dom_id)) + 1)
|
||||
#else
|
||||
#define GDT_IDX_LDT(dom_id) (GDT_NUM_FIXED_DESC + (dom_id))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#else
|
||||
#define GDT_IDX_CODE GDT_IDX_CODE_FLAT
|
||||
#define GDT_IDX_CODE_INT GDT_IDX_CODE_FLAT
|
||||
#define GDT_IDX_CODE_EXC GDT_IDX_CODE_FLAT
|
||||
#define GDT_IDX_DATA GDT_IDX_DATA_FLAT
|
||||
#define GDT_IDX_STK GDT_IDX_DATA_FLAT
|
||||
#define GDT_IDX_STK_INT GDT_IDX_DATA_FLAT
|
||||
#define GDT_IDX_STK_EXC GDT_IDX_DATA_FLAT
|
||||
#endif
|
||||
|
||||
#define GDT_SEL(idx, rpl) (((idx) << 3) | (rpl))
|
||||
|
||||
#define DT_SEL_GET_IDX(sel) ((sel) >> 3)
|
||||
|
||||
#define DT_SEL_GET_RPL(sel) ((sel) & 3)
|
||||
|
||||
#define GDT_SEL_NULL GDT_SEL(GDT_IDX_NULL, 0)
|
||||
#define GDT_SEL_CODE_FLAT GDT_SEL(GDT_IDX_CODE_FLAT, PRIV_LVL_EXC)
|
||||
#define GDT_SEL_DATA_FLAT GDT_SEL(GDT_IDX_DATA_FLAT, PRIV_LVL_EXC)
|
||||
|
||||
#define GDT_SEL_CODE GDT_SEL(GDT_IDX_CODE, PRIV_LVL_USER)
|
||||
#define GDT_SEL_CODE_INT GDT_SEL(GDT_IDX_CODE_INT, PRIV_LVL_INT)
|
||||
#define GDT_SEL_CODE_EXC GDT_SEL(GDT_IDX_CODE_EXC, PRIV_LVL_EXC)
|
||||
|
||||
#define GDT_SEL_DATA GDT_SEL(GDT_IDX_DATA, PRIV_LVL_EXC)
|
||||
#define GDT_SEL_DATA_KERN_EXC GDT_SEL(GDT_IDX_DATA_KERN_EXC, PRIV_LVL_EXC)
|
||||
|
||||
#define GDT_SEL_STK GDT_SEL(GDT_IDX_STK, PRIV_LVL_USER)
|
||||
#define GDT_SEL_STK_INT GDT_SEL(GDT_IDX_STK_INT, PRIV_LVL_INT)
|
||||
#define GDT_SEL_STK_EXC GDT_SEL(GDT_IDX_STK_EXC, PRIV_LVL_EXC)
|
||||
|
||||
#define GDT_SEL_TSS(dom_id) GDT_SEL(GDT_IDX_TSS(dom_id), PRIV_LVL_USER)
|
||||
#define GDT_SEL_LDT(dom_id) GDT_SEL(GDT_IDX_LDT(dom_id), PRIV_LVL_USER)
|
||||
|
||||
#endif /* CPU_X86_MM_GDT_LAYOUT_H_ */
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_LDT_LAYOUT_H_
|
||||
#define CPU_X86_MM_LDT_LAYOUT_H_
|
||||
|
||||
#include "gdt-layout.h"
|
||||
|
||||
/* Each LDT can contain up to this many descriptors, but some protection
|
||||
* domains may not use all of the slots.
|
||||
*/
|
||||
#define LDT_NUM_DESC 3
|
||||
|
||||
/**
|
||||
* Provides access to kernel data. Most protection domains are granted at most
|
||||
* read-only access, but the kernel protection domain is granted read/write
|
||||
* access.
|
||||
*/
|
||||
#define LDT_IDX_KERN 0
|
||||
/** Maps a device MMIO range */
|
||||
#define LDT_IDX_MMIO 1
|
||||
/** Maps domain-defined metadata */
|
||||
#define LDT_IDX_META 2
|
||||
|
||||
#define LDT_SEL(idx, rpl) (GDT_SEL(idx, rpl) | (1 << 2))
|
||||
|
||||
#define LDT_SEL_KERN LDT_SEL(LDT_IDX_KERN, PRIV_LVL_USER)
|
||||
#define LDT_SEL_MMIO LDT_SEL(LDT_IDX_MMIO, PRIV_LVL_USER)
|
||||
#define LDT_SEL_META LDT_SEL(LDT_IDX_META, PRIV_LVL_USER)
|
||||
#define LDT_SEL_STK LDT_SEL(LDT_IDX_STK, PRIV_LVL_USER)
|
||||
|
||||
#endif /* CPU_X86_MM_LDT_LAYOUT_H_ */
|
|
@ -1,248 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gdt.h"
|
||||
#include "helpers.h"
|
||||
#include "prot-domains.h"
|
||||
#include "segmentation.h"
|
||||
#include "stacks.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint32_t
|
||||
segment_desc_compute_base(segment_desc_t desc)
|
||||
{
|
||||
return (desc.base_hi << 24) | (desc.base_mid << 16) | desc.base_lo;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
prot_domains_reg_multi_seg(volatile struct dom_kern_data ATTR_KERN_ADDR_SPACE *dkd,
|
||||
uintptr_t mmio, size_t mmio_sz,
|
||||
uintptr_t meta, size_t meta_sz)
|
||||
{
|
||||
segment_desc_t desc;
|
||||
dom_id_t dom_id = PROT_DOMAINS_GET_DOM_ID(dkd);
|
||||
uint32_t kern_data_len;
|
||||
uint32_t tmp;
|
||||
|
||||
if((dkd < prot_domains_kern_data) ||
|
||||
(prot_domains_kern_data_end <= dkd) ||
|
||||
(((((uintptr_t)dkd) - (uintptr_t)prot_domains_kern_data) %
|
||||
sizeof(dom_kern_data_t)) != 0)) {
|
||||
halt();
|
||||
}
|
||||
|
||||
KERN_READL(tmp, dkd->ldt[DT_SEL_GET_IDX(LDT_SEL_KERN)].raw_hi);
|
||||
if(tmp != 0) {
|
||||
/* This PDCS was previously initialized, which is disallowed. */
|
||||
halt();
|
||||
}
|
||||
|
||||
/* Initialize descriptors */
|
||||
|
||||
if(dom_id == DOM_ID_kern) {
|
||||
kern_data_len = (uint32_t)&_ebss_kern_addr;
|
||||
} else {
|
||||
/* Non-kernel protection domains do not need to access the protection
|
||||
* domain control structures, and they may contain saved register values
|
||||
* that are private to each domain.
|
||||
*/
|
||||
kern_data_len = (uint32_t)&_ebss_syscall_addr;
|
||||
}
|
||||
kern_data_len -= (uint32_t)&_sbss_kern_addr;
|
||||
|
||||
segment_desc_init(&desc, (uint32_t)&_sbss_kern_addr, kern_data_len,
|
||||
/* Every protection domain requires at least read-only access to kernel
|
||||
data to read dom_client_data structures and to support the system call
|
||||
dispatcher, if applicable. Only the kernel protection domain is granted
|
||||
read/write access to the kernel data. */
|
||||
((dom_id == DOM_ID_kern) ?
|
||||
SEG_TYPE_DATA_RDWR :
|
||||
SEG_TYPE_DATA_RDONLY) |
|
||||
SEG_FLAG(DPL, PRIV_LVL_USER) |
|
||||
SEG_GRAN_BYTE | SEG_DESCTYPE_NSYS);
|
||||
|
||||
KERN_WRITEL(dkd->ldt[LDT_IDX_KERN].raw_lo, desc.raw_lo);
|
||||
KERN_WRITEL(dkd->ldt[LDT_IDX_KERN].raw_hi, desc.raw_hi);
|
||||
|
||||
if(mmio_sz != 0) {
|
||||
if(SEG_MAX_BYTE_GRAN_LEN < mmio_sz) {
|
||||
halt();
|
||||
}
|
||||
|
||||
segment_desc_init(&desc, mmio, mmio_sz,
|
||||
SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_GRAN_BYTE |
|
||||
SEG_DESCTYPE_NSYS | SEG_TYPE_DATA_RDWR);
|
||||
} else {
|
||||
desc.raw = SEG_DESC_NOT_PRESENT;
|
||||
}
|
||||
|
||||
KERN_WRITEL(dkd->ldt[LDT_IDX_MMIO].raw_lo, desc.raw_lo);
|
||||
KERN_WRITEL(dkd->ldt[LDT_IDX_MMIO].raw_hi, desc.raw_hi);
|
||||
|
||||
if(meta_sz != 0) {
|
||||
if(SEG_MAX_BYTE_GRAN_LEN < meta_sz) {
|
||||
halt();
|
||||
}
|
||||
|
||||
segment_desc_init(&desc, meta, meta_sz,
|
||||
SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_GRAN_BYTE |
|
||||
SEG_DESCTYPE_NSYS | SEG_TYPE_DATA_RDWR);
|
||||
} else {
|
||||
desc.raw = SEG_DESC_NOT_PRESENT;
|
||||
}
|
||||
|
||||
KERN_WRITEL(dkd->ldt[LDT_IDX_META].raw_lo, desc.raw_lo);
|
||||
KERN_WRITEL(dkd->ldt[LDT_IDX_META].raw_hi, desc.raw_hi);
|
||||
|
||||
segment_desc_init(&desc,
|
||||
KERN_DATA_OFF_TO_PHYS_ADDR(dkd->ldt),
|
||||
sizeof(dkd->ldt),
|
||||
SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_GRAN_BYTE |
|
||||
SEG_DESCTYPE_SYS | SEG_TYPE_LDT);
|
||||
gdt_insert(GDT_IDX_LDT(dom_id), desc);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
prot_domains_gdt_init()
|
||||
{
|
||||
int i;
|
||||
segment_desc_t desc;
|
||||
|
||||
segment_desc_init(&desc,
|
||||
(uint32_t)&_stext_addr,
|
||||
((uint32_t)&_etext_addr) - (uint32_t)&_stext_addr,
|
||||
SEG_FLAG(DPL, PRIV_LVL_EXC) | SEG_GRAN_BYTE |
|
||||
SEG_DESCTYPE_NSYS |
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
|
||||
/* The general protection fault handler requires read access to CS */
|
||||
SEG_TYPE_CODE_EXRD
|
||||
#else
|
||||
SEG_TYPE_CODE_EX
|
||||
#endif
|
||||
);
|
||||
gdt_insert_boot(GDT_IDX_CODE_EXC, desc);
|
||||
|
||||
segment_desc_init(&desc,
|
||||
(uint32_t)&_sdata_addr,
|
||||
((uint32_t)&_edata_addr) - (uint32_t)&_sdata_addr,
|
||||
SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_GRAN_BYTE |
|
||||
SEG_DESCTYPE_NSYS | SEG_TYPE_DATA_RDWR);
|
||||
gdt_insert_boot(GDT_IDX_DATA, desc);
|
||||
|
||||
segment_desc_init(&desc,
|
||||
(uint32_t)&_sbss_kern_addr,
|
||||
((uint32_t)&_ebss_kern_addr) -
|
||||
(uint32_t)&_sbss_kern_addr,
|
||||
SEG_FLAG(DPL, PRIV_LVL_EXC) | SEG_GRAN_BYTE |
|
||||
SEG_DESCTYPE_NSYS | SEG_TYPE_DATA_RDWR);
|
||||
gdt_insert_boot(GDT_IDX_DATA_KERN_EXC, desc);
|
||||
|
||||
segment_desc_init(&desc,
|
||||
(uint32_t)DATA_OFF_TO_PHYS_ADDR(stacks_main),
|
||||
STACKS_SIZE_MAIN,
|
||||
SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_GRAN_BYTE |
|
||||
SEG_DESCTYPE_NSYS | SEG_TYPE_DATA_RDWR);
|
||||
gdt_insert_boot(GDT_IDX_STK, desc);
|
||||
|
||||
segment_desc_set_limit(&desc, STACKS_SIZE_MAIN + STACKS_SIZE_INT);
|
||||
SEG_SET_FLAG(desc, DPL, PRIV_LVL_INT);
|
||||
gdt_insert_boot(GDT_IDX_STK_INT, desc);
|
||||
|
||||
segment_desc_set_limit(&desc,
|
||||
STACKS_SIZE_MAIN +
|
||||
STACKS_SIZE_INT +
|
||||
STACKS_SIZE_EXC);
|
||||
SEG_SET_FLAG(desc, DPL, PRIV_LVL_EXC);
|
||||
gdt_insert_boot(GDT_IDX_STK_EXC, desc);
|
||||
|
||||
/* Not all domains will necessarily be initialized, so this initially marks
|
||||
* all per-domain descriptors not-present.
|
||||
*/
|
||||
desc.raw = SEG_DESC_NOT_PRESENT;
|
||||
for(i = 0; i < PROT_DOMAINS_ACTUAL_CNT; i++) {
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS
|
||||
gdt_insert_boot(GDT_IDX_TSS(i), desc);
|
||||
#endif
|
||||
gdt_insert_boot(GDT_IDX_LDT(i), desc);
|
||||
}
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"mov %[_default_data_], %%ds\n\t"
|
||||
"mov %[_default_data_], %%es\n\t"
|
||||
"mov %[_kern_data_], %%" SEG_KERN "s\n\t"
|
||||
:
|
||||
: [_default_data_] "r"(GDT_SEL_DATA),
|
||||
[_kern_data_] "r"(GDT_SEL_DATA_KERN_EXC));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
multi_segment_launch_kernel(void)
|
||||
{
|
||||
/* Update segment registers. */
|
||||
__asm__ __volatile__ (
|
||||
"mov %[_data_seg_], %%ds\n\t"
|
||||
"mov %[_data_seg_], %%es\n\t"
|
||||
"mov %[_kern_seg_], %%" SEG_KERN "s\n\t"
|
||||
"mov %[_data_seg_], %%" SEG_META "s\n\t"
|
||||
:
|
||||
: [_data_seg_] "r" (GDT_SEL_DATA),
|
||||
[_kern_seg_] "r" (LDT_SEL_KERN)
|
||||
);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
prot_domains_enable_mmio(void)
|
||||
{
|
||||
__asm__ __volatile__ ("mov %0, %%" SEG_MMIO "s" :: "r" (LDT_SEL_MMIO));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
prot_domains_disable_mmio(void)
|
||||
{
|
||||
__asm__ __volatile__ ("mov %0, %%" SEG_KERN "s" :: "r" (LDT_SEL_KERN));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uintptr_t
|
||||
prot_domains_lookup_meta_phys_base(dom_client_data_t ATTR_KERN_ADDR_SPACE *drv)
|
||||
{
|
||||
dom_id_t dom_id;
|
||||
segment_desc_t desc;
|
||||
volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *dkd;
|
||||
|
||||
KERN_READL(dom_id, drv->dom_id);
|
||||
|
||||
dkd = prot_domains_kern_data + dom_id;
|
||||
|
||||
KERN_READL(desc.raw_lo, dkd->ldt[DT_SEL_GET_IDX(LDT_SEL_META)].raw_lo);
|
||||
KERN_READL(desc.raw_hi, dkd->ldt[DT_SEL_GET_IDX(LDT_SEL_META)].raw_hi);
|
||||
|
||||
return segment_desc_compute_base(desc);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,195 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_MULTI_SEGMENT_H_
|
||||
#define CPU_X86_MM_MULTI_SEGMENT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "helpers.h"
|
||||
#include "ldt-layout.h"
|
||||
|
||||
#ifdef __clang__
|
||||
#define __SEG_FS
|
||||
#define __seg_fs __attribute__((address_space(257)))
|
||||
#define __SEG_GS
|
||||
#define __seg_gs __attribute__((address_space(256)))
|
||||
#endif
|
||||
|
||||
#ifdef __SEG_FS
|
||||
#define ATTR_MMIO_ADDR_SPACE __seg_fs
|
||||
#define ATTR_KERN_ADDR_SPACE __seg_fs
|
||||
#else
|
||||
#define ATTR_KERN_ADDR_SPACE
|
||||
#endif
|
||||
#ifdef __SEG_GS
|
||||
#define ATTR_META_ADDR_SPACE __seg_gs
|
||||
#endif
|
||||
|
||||
void prot_domains_reg_multi_seg(volatile struct dom_kern_data ATTR_KERN_ADDR_SPACE *dkd,
|
||||
uintptr_t mmio, size_t mmio_sz,
|
||||
uintptr_t meta, size_t meta_sz);
|
||||
void multi_segment_launch_kernel(void);
|
||||
|
||||
#define MULTI_SEGMENT_ENTER_ISR(exc) \
|
||||
"mov $" EXP_STRINGIFY(GDT_SEL_DATA) ", %%eax\n\t" \
|
||||
/* Refresh DS and ES in case the userspace code corrupted them. */ \
|
||||
"mov %%eax, %%ds\n\t" \
|
||||
"mov %%eax, %%es\n\t" \
|
||||
/* Refresh SEG_KERN. */ \
|
||||
"mov $" EXP_STRINGIFY(LDT_SEL_KERN) ", %%eax\n\t" \
|
||||
"mov %%eax, %%" SEG_KERN "s\n\t" \
|
||||
".if " #exc "\n\t" \
|
||||
/* It is possible that a routine performing MMIO is being interrupted. */ \
|
||||
/* Thus, it is necessary to save and restore the MMIO segment register */ \
|
||||
/* (in a callee-saved register). */ \
|
||||
"mov %%" SEG_MMIO "s, %%ebp\n\t" \
|
||||
"mov $" EXP_STRINGIFY(GDT_SEL_DATA_KERN_EXC) ", %%eax\n\t" \
|
||||
"mov %%eax, %%" SEG_KERN "s\n\t" \
|
||||
".endif\n\t"
|
||||
#define MULTI_SEGMENT_LEAVE_ISR(exc) \
|
||||
".if " #exc "\n\t" \
|
||||
"mov %%ebp, %%" SEG_MMIO "s\n\t" \
|
||||
".endif\n\t"
|
||||
|
||||
/**
|
||||
* The MMIO region is tightly bounded within a segment, so its base offset is
|
||||
* always 0.
|
||||
*/
|
||||
#define PROT_DOMAINS_MMIO(dcd) 0
|
||||
/**
|
||||
* The metadata region is tightly bounded within a segment, so its base offset
|
||||
* is always 0.
|
||||
*/
|
||||
#define PROT_DOMAINS_META(dcd) 0
|
||||
|
||||
#define SEG_MMIO "f" /**< For MMIO accesses, when enabled. */
|
||||
#define SEG_KERN "f" /**< For kernel data accesses */
|
||||
#define SEG_META "g" /**< For metadata accesses */
|
||||
|
||||
#define _SEG_READL(seg, dst, src) \
|
||||
__asm__ __volatile__ ( \
|
||||
"movl %%" seg "s:%[src_], %[dst_]" : [dst_]"=r"(dst) : [src_]"m"(src))
|
||||
|
||||
#define _SEG_READW(seg, dst, src) \
|
||||
__asm__ __volatile__ ( \
|
||||
"movw %%" seg "s:%[src_], %[dst_]" : [dst_]"=r"(dst) : [src_]"m"(src))
|
||||
|
||||
#define _SEG_READB(seg, dst, src) \
|
||||
__asm__ __volatile__ ( \
|
||||
"movb %%" seg "s:%[src_], %[dst_]" : [dst_]"=q"(dst) : [src_]"m"(src))
|
||||
|
||||
#define _SEG_WRITEL(seg, dst, src) \
|
||||
__asm__ __volatile__ ( \
|
||||
"movl %[src_], %%" seg "s:%[dst_]" \
|
||||
: [dst_]"=m"(dst) : [src_]"r"((uint32_t)(src)))
|
||||
|
||||
#define _SEG_WRITEW(seg, dst, src) \
|
||||
__asm__ __volatile__ ( \
|
||||
"movw %[src_], %%" seg "s:%[dst_]" \
|
||||
: [dst_]"=m"(dst) : [src_]"r"((uint16_t)(src)))
|
||||
|
||||
#define _SEG_WRITEB(seg, dst, src) \
|
||||
__asm__ __volatile__ ( \
|
||||
"movb %[src_], %%" seg "s:%[dst_]" \
|
||||
: [dst_]"=m"(dst) : [src_]"q"((uint8_t)(src)))
|
||||
|
||||
#ifndef __SEG_FS
|
||||
#define MMIO_READL(dst, src) _SEG_READL(SEG_MMIO, dst, src)
|
||||
#define MMIO_READW(dst, src) _SEG_READW(SEG_MMIO, dst, src)
|
||||
#define MMIO_READB(dst, src) _SEG_READB(SEG_MMIO, dst, src)
|
||||
#define MMIO_WRITEL(dst, src) _SEG_WRITEL(SEG_MMIO, dst, src)
|
||||
#define MMIO_WRITEW(dst, src) _SEG_WRITEW(SEG_MMIO, dst, src)
|
||||
#define MMIO_WRITEB(dst, src) _SEG_WRITEB(SEG_MMIO, dst, src)
|
||||
|
||||
#define KERN_READL(dst, src) _SEG_READL(SEG_KERN, dst, src)
|
||||
#define KERN_READW(dst, src) _SEG_READW(SEG_KERN, dst, src)
|
||||
#define KERN_READB(dst, src) _SEG_READB(SEG_KERN, dst, src)
|
||||
#define KERN_WRITEL(dst, src) _SEG_WRITEL(SEG_KERN, dst, src)
|
||||
#define KERN_WRITEW(dst, src) _SEG_WRITEW(SEG_KERN, dst, src)
|
||||
#define KERN_WRITEB(dst, src) _SEG_WRITEB(SEG_KERN, dst, src)
|
||||
#endif
|
||||
|
||||
#ifndef __SEG_GS
|
||||
#define META_READL(dst, src) _SEG_READL(SEG_META, dst, src)
|
||||
#define META_READW(dst, src) _SEG_READW(SEG_META, dst, src)
|
||||
#define META_READB(dst, src) _SEG_READB(SEG_META, dst, src)
|
||||
#define META_WRITEL(dst, src) _SEG_WRITEL(SEG_META, dst, src)
|
||||
#define META_WRITEW(dst, src) _SEG_WRITEW(SEG_META, dst, src)
|
||||
#define META_WRITEB(dst, src) _SEG_WRITEB(SEG_META, dst, src)
|
||||
#endif
|
||||
|
||||
#define MEMCPY_FROM_META(dst, src, sz) \
|
||||
{ \
|
||||
uintptr_t __dst = (uintptr_t)(dst); \
|
||||
uintptr_t __src = (uintptr_t)(src); \
|
||||
size_t __sz = (size_t)(sz); \
|
||||
__asm__ __volatile__ ( \
|
||||
"rep movsb %%" SEG_META "s:(%%esi), %%es:(%%edi)\n\t" \
|
||||
: "+D"(__dst), "+S"(__src), "+c"(__sz)); \
|
||||
}
|
||||
|
||||
#define MEMCPY_TO_META(dst, src, sz) \
|
||||
{ \
|
||||
uintptr_t __dst = (uintptr_t)(dst); \
|
||||
uintptr_t __src = (uintptr_t)(src); \
|
||||
size_t __sz = (size_t)(sz); \
|
||||
__asm__ __volatile__ ( \
|
||||
"push %%es\n\t" \
|
||||
"push %%" SEG_META "s\n\t" \
|
||||
"pop %%es\n\t" \
|
||||
"rep movsb\n\t" \
|
||||
"pop %%es\n\t" \
|
||||
: "+D"(__dst), "+S"(__src), "+c"(__sz)); \
|
||||
}
|
||||
|
||||
/** Compute physical address from offset into kernel data space */
|
||||
#define KERN_DATA_OFF_TO_PHYS_ADDR(x) \
|
||||
(((uintptr_t)&_sbss_kern_addr) + (uintptr_t)(x))
|
||||
/** Compute physical address from offset into default data space */
|
||||
#define DATA_OFF_TO_PHYS_ADDR(x) \
|
||||
(((uintptr_t)&_sdata_addr) + (uintptr_t)(x))
|
||||
/** Compute kernel data offset from physical address in kernel data space */
|
||||
#define PHYS_ADDR_TO_KERN_DATA_OFF(x) \
|
||||
(((uintptr_t)(x)) - (uintptr_t)&_sbss_kern_addr)
|
||||
|
||||
/**
|
||||
* In multi-segment protection domain implementations, it is sufficient to just
|
||||
* compare incoming pointers against the frame pointer. All incoming pointers
|
||||
* are dereferenced in the main data segment, which only maps the stacks and
|
||||
* the shared data section. Since the shared data section is at a higher
|
||||
* address range than the stacks, the frame pointer check is sufficient.
|
||||
*/
|
||||
#define PROT_DOMAINS_CHECK_INCOMING_PTR PROT_DOMAINS_CHECK_INCOMING_PTR_EBP
|
||||
|
||||
void prot_domains_enable_mmio(void);
|
||||
void prot_domains_disable_mmio(void);
|
||||
|
||||
#endif /* CPU_X86_MM_MULTI_SEGMENT_H_ */
|
|
@ -1,297 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "dma.h"
|
||||
#include "gdt.h"
|
||||
#include "gdt-layout.h"
|
||||
#include "helpers.h"
|
||||
#include "idt.h"
|
||||
#include "paging.h"
|
||||
#include "prot-domains.h"
|
||||
#include "segmentation.h"
|
||||
#include "stacks.h"
|
||||
#include "syscalls.h"
|
||||
#include "tss.h"
|
||||
|
||||
/*#define DBG_PAGE_ALLOC*/
|
||||
|
||||
/* Enable PAE-mode paging */
|
||||
#define CR4_PAE BIT(5)
|
||||
|
||||
/* Extended Feature Enables MSR */
|
||||
#define MSR_EFER 0xC0000080
|
||||
|
||||
/* Enable Execute Disable bit support */
|
||||
#define EFER_NXE BIT(11)
|
||||
|
||||
/* Root page-directory-pointer table */
|
||||
static pdpt_t root_pgtbl __attribute__((aligned(32))) ATTR_BSS_KERN;
|
||||
/* Although the following page tables must be page-aligned, it is infeasible to
|
||||
* apply the "aligned(4096)" attribute for the reasons described in the linker
|
||||
* script.
|
||||
*/
|
||||
/* Second-level page directory */
|
||||
static page_table_t
|
||||
second_lvl_pgtbl ATTR_BSS_KERN_PAGE_ALIGNED;
|
||||
/* Leaf-level page table */
|
||||
static page_table_t leaf_pgtbl ATTR_BSS_KERN_PAGE_ALIGNED;
|
||||
|
||||
#define LINEAR_ADDR_BOUND (MIN_PAGE_SIZE * ENTRIES_PER_PAGE_TABLE)
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
prot_domains_reg(dom_client_data_t *dcd,
|
||||
uintptr_t mmio,
|
||||
size_t mmio_sz,
|
||||
uintptr_t meta,
|
||||
size_t meta_sz,
|
||||
bool pio)
|
||||
{
|
||||
dom_id_t dom_id = dcd->dom_id;
|
||||
volatile struct dom_kern_data *dkd =
|
||||
prot_domains_kern_data + dom_id;
|
||||
|
||||
/* All addresses and sizes must be page-aligned */
|
||||
if((PROT_DOMAINS_ACTUAL_CNT <= dom_id) ||
|
||||
((mmio & (MIN_PAGE_SIZE - 1)) != 0) ||
|
||||
((mmio_sz & (MIN_PAGE_SIZE - 1)) != 0) ||
|
||||
((meta & (MIN_PAGE_SIZE - 1)) != 0) ||
|
||||
((meta_sz & (MIN_PAGE_SIZE - 1)) != 0) ||
|
||||
(PROT_DOMAINS_MAX_MMIO_SZ < mmio_sz) ||
|
||||
(LINEAR_ADDR_BOUND < (PROT_DOMAINS_META_LINEAR_BASE + meta_sz))) {
|
||||
halt();
|
||||
}
|
||||
|
||||
if((dkd->flags & PROT_DOMAINS_FLAG_INITED) == PROT_DOMAINS_FLAG_INITED) {
|
||||
halt();
|
||||
}
|
||||
|
||||
dkd->mmio = mmio;
|
||||
dkd->mmio_sz = mmio_sz;
|
||||
dkd->meta = meta;
|
||||
dkd->meta_sz = meta_sz;
|
||||
dkd->flags = PROT_DOMAINS_FLAG_INITED;
|
||||
if(pio) {
|
||||
dkd->flags |= PROT_DOMAINS_FLAG_PIO;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void __attribute__((regparm(3)))
|
||||
set_ptes(uintptr_t start_la, uintptr_t start_pa, uintptr_t end_pa,
|
||||
pte_t template)
|
||||
{
|
||||
#ifdef DBG_PAGE_ALLOC
|
||||
#warning Checking page allocations at runtime.
|
||||
|
||||
if(((start_la & (MIN_PAGE_SIZE - 1)) != 0) ||
|
||||
((start_pa & (MIN_PAGE_SIZE - 1)) != 0) ||
|
||||
((start_la & (MIN_PAGE_SIZE - 1)) != 0) ||
|
||||
((end_pa & (MIN_PAGE_SIZE - 1)) != 0) ||
|
||||
(LINEAR_ADDR_BOUND <= (start_la + (end_pa - start_pa)))) {
|
||||
halt();
|
||||
}
|
||||
#endif
|
||||
|
||||
while(start_pa < end_pa) {
|
||||
template.addr = start_pa >> 12;
|
||||
|
||||
leaf_pgtbl[start_la >> MIN_PAGE_SIZE_SHAMT] = template;
|
||||
|
||||
#ifdef X86_CONF_USE_INVLPG
|
||||
__asm__("invlpg %0" :: "m" (*(uint8_t *)start_la));
|
||||
#endif
|
||||
|
||||
start_la += MIN_PAGE_SIZE;
|
||||
start_pa += MIN_PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void __attribute__((fastcall))
|
||||
set_ptes_identity_map(uintptr_t start_pa, uintptr_t end_pa, pte_t template)
|
||||
{
|
||||
set_ptes(start_pa, start_pa, end_pa, template);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static inline uint32_t __attribute__((always_inline))
|
||||
prot_domains_switch(dom_id_t from_id, dom_id_t to_id,
|
||||
interrupt_stack_t *intr_stk)
|
||||
{
|
||||
volatile dom_kern_data_t *from, *to;
|
||||
|
||||
from = prot_domains_kern_data + from_id;
|
||||
to = prot_domains_kern_data + to_id;
|
||||
|
||||
if((from_id == DOM_ID_kern) ||
|
||||
(to_id == DOM_ID_kern)) {
|
||||
pte_t to_kern_data_pte = { .raw = 0 };
|
||||
to_kern_data_pte.present = 1;
|
||||
to_kern_data_pte.exec_disable = 1;
|
||||
/* The kernel data region should always be accessible to supervisory code,
|
||||
* but it is only accessible to user mode in the kernel protection domain.
|
||||
*/
|
||||
to_kern_data_pte.user_accessible = 1;
|
||||
if(to_id == DOM_ID_kern) {
|
||||
to_kern_data_pte.writable = 1;
|
||||
}
|
||||
|
||||
set_ptes_identity_map((uintptr_t)&_sbss_kern_addr,
|
||||
(uintptr_t)&_ebss_syscall_addr,
|
||||
to_kern_data_pte);
|
||||
|
||||
if(to_id != DOM_ID_kern) {
|
||||
to_kern_data_pte.user_accessible = 0;
|
||||
to_kern_data_pte.writable = 0;
|
||||
}
|
||||
|
||||
set_ptes_identity_map((uintptr_t)&_ebss_syscall_addr,
|
||||
(uintptr_t)&_ebss_kern_addr,
|
||||
to_kern_data_pte);
|
||||
}
|
||||
|
||||
if(to->mmio_sz != 0) {
|
||||
pte_t pte = { .raw = 0 };
|
||||
pte.present = 1;
|
||||
pte.exec_disable = 1;
|
||||
pte.user_accessible = 1;
|
||||
pte.writable = 1;
|
||||
/* disable caching of MMIO accesses */
|
||||
pte.pcd = 1;
|
||||
|
||||
set_ptes(PROT_DOMAINS_MMIO_LINEAR_BASE,
|
||||
to->mmio,
|
||||
to->mmio + to->mmio_sz,
|
||||
pte);
|
||||
}
|
||||
if(to->mmio_sz < from->mmio_sz) {
|
||||
pte_t pte = { .raw = 0 };
|
||||
|
||||
set_ptes_identity_map(PROT_DOMAINS_MMIO_LINEAR_BASE + to->mmio_sz,
|
||||
PROT_DOMAINS_MMIO_LINEAR_BASE + from->mmio_sz,
|
||||
pte);
|
||||
}
|
||||
|
||||
if(to->meta_sz != 0) {
|
||||
pte_t pte = { .raw = 0 };
|
||||
pte.present = 1;
|
||||
pte.exec_disable = 1;
|
||||
pte.user_accessible = 1;
|
||||
pte.writable = 1;
|
||||
|
||||
set_ptes(PROT_DOMAINS_META_LINEAR_BASE,
|
||||
to->meta,
|
||||
to->meta + to->meta_sz,
|
||||
pte);
|
||||
}
|
||||
if(to->meta_sz < from->meta_sz) {
|
||||
pte_t pte = { .raw = 0 };
|
||||
|
||||
set_ptes_identity_map(PROT_DOMAINS_META_LINEAR_BASE + to->mmio_sz,
|
||||
PROT_DOMAINS_META_LINEAR_BASE + from->mmio_sz,
|
||||
pte);
|
||||
}
|
||||
|
||||
#ifndef X86_CONF_USE_INVLPG
|
||||
__asm__ __volatile__ ("mov %%cr3, %%eax\n\t"
|
||||
"mov %%eax, %%cr3\n\t" ::: "eax");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
prot_domains_gdt_init(void)
|
||||
{
|
||||
gdt_copy_desc_change_dpl(GDT_IDX_DATA, GDT_IDX_DATA_FLAT, PRIV_LVL_USER);
|
||||
gdt_copy_desc_change_dpl(GDT_IDX_STK_INT, GDT_IDX_STK_EXC, PRIV_LVL_INT);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
prot_domains_impl_init(void)
|
||||
{
|
||||
pte_t pte = { .raw = 0 };
|
||||
|
||||
syscalls_int_init();
|
||||
|
||||
/* Initialize page table: */
|
||||
|
||||
pte.present = 1;
|
||||
pte.addr = ((uint32_t)second_lvl_pgtbl) >> MIN_PAGE_SIZE_SHAMT;
|
||||
|
||||
root_pgtbl[0] = pte;
|
||||
|
||||
pte.writable = 1;
|
||||
pte.user_accessible = 1;
|
||||
pte.addr = ((uint32_t)leaf_pgtbl) >> MIN_PAGE_SIZE_SHAMT;
|
||||
|
||||
second_lvl_pgtbl[0] = pte;
|
||||
|
||||
/* Map code sections: */
|
||||
|
||||
pte.writable = 0;
|
||||
set_ptes_identity_map((uintptr_t)&_stext_addr, (uintptr_t)&_etext_addr, pte);
|
||||
|
||||
/* Map data sections: */
|
||||
|
||||
pte.writable = 1;
|
||||
pte.exec_disable = 1;
|
||||
set_ptes_identity_map((uintptr_t)stacks_main,
|
||||
(uintptr_t)stacks_main +
|
||||
STACKS_SIZE_MAIN +
|
||||
STACKS_SIZE_EXC +
|
||||
STACKS_SIZE_INT,
|
||||
pte);
|
||||
set_ptes_identity_map((uintptr_t)&_sdata_addr, (uintptr_t)&_edata_addr, pte);
|
||||
|
||||
/* Enable XD bit support */
|
||||
__asm__ __volatile__ ("wrmsr" :: "c" (MSR_EFER), "a" (EFER_NXE), "d" (0));
|
||||
|
||||
/* Enable PAE */
|
||||
__asm__ __volatile__ ("mov %%cr4, %%eax\n\t"
|
||||
"or %0, %%eax\n\t"
|
||||
"mov %%eax, %%cr4\n\t"
|
||||
:
|
||||
: "r" (CR4_PAE)
|
||||
: "eax");
|
||||
|
||||
/* Load CR3 */
|
||||
__asm__ __volatile__ ("mov %0, %%cr3" :: "r" (root_pgtbl));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
uintptr_t
|
||||
prot_domains_lookup_meta_phys_base(dom_client_data_t *drv)
|
||||
{
|
||||
return prot_domains_kern_data[drv->dom_id].meta;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Enable inter-procedural optimization with procedures in the following file:
|
||||
*/
|
||||
#include "syscalls-int.c"
|
|
@ -1,114 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_PAGING_PROT_DOMAINS_H_
|
||||
#define CPU_X86_MM_PAGING_PROT_DOMAINS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "dma.h"
|
||||
#include "helpers.h"
|
||||
#include "paging.h"
|
||||
#include "syscalls-int.h"
|
||||
|
||||
struct dom_kern_data {
|
||||
/** Base physical address of optional MMIO region */
|
||||
uintptr_t mmio;
|
||||
/** Number of (contiguous) pages in MMIO region */
|
||||
size_t mmio_sz;
|
||||
/** Base physical address of optional metadata region */
|
||||
uintptr_t meta;
|
||||
/** Number of (contiguous) pages in metadata region */
|
||||
size_t meta_sz;
|
||||
/** Flags are defined with the prefix PROT_DOMAINS_FLAG in prot-domains.h */
|
||||
uint32_t flags;
|
||||
/**
|
||||
* Original return address from call stack when this protection domain
|
||||
* invoked some other protection domain. This serves to control the return
|
||||
* entrypoint. The callee is not permitted to modify this value (unless the
|
||||
* callee is the kernel protection domain).
|
||||
*/
|
||||
uintptr_t orig_ret_addr;
|
||||
|
||||
/* align to next-larger power of 2 to enable usage of shifting instead of
|
||||
* multiplication to index an array of these structures.
|
||||
*/
|
||||
} __attribute__((aligned(32)));
|
||||
|
||||
/** Linear base address at which to map the MMIO region. */
|
||||
#define PROT_DOMAINS_MMIO_LINEAR_BASE (MIN_PAGE_SIZE + (uintptr_t)&_ebss_kern_addr)
|
||||
|
||||
/** Maximum supported size of MMIO region */
|
||||
#define PROT_DOMAINS_MAX_MMIO_SZ 0x4000
|
||||
|
||||
/** Linear base address at which to map the metadata region */
|
||||
#define PROT_DOMAINS_META_LINEAR_BASE \
|
||||
(MIN_PAGE_SIZE + (PROT_DOMAINS_MMIO_LINEAR_BASE + PROT_DOMAINS_MAX_MMIO_SZ))
|
||||
|
||||
#define PROT_DOMAINS_META_OFF_TO_PHYS(off, meta_phys_base) \
|
||||
((meta_phys_base) + ((off) - PROT_DOMAINS_META_LINEAR_BASE))
|
||||
|
||||
/** Any MMIO region mapping always starts at a particular linear address. */
|
||||
#define PROT_DOMAINS_MMIO(dcd) PROT_DOMAINS_MMIO_LINEAR_BASE
|
||||
/**
|
||||
* Any metadata region mapping always starts at a particular linear address.
|
||||
*/
|
||||
#define PROT_DOMAINS_META(dcd) PROT_DOMAINS_META_LINEAR_BASE
|
||||
|
||||
#define PROT_DOMAINS_ENTER_ISR(exc) \
|
||||
PROT_DOMAINS_ENTER_ISR_COMMON(exc)
|
||||
#define PROT_DOMAINS_LEAVE_ISR(exc) PROT_DOMAINS_LEAVE_ISR_COMMON(exc)
|
||||
|
||||
/* Enable paging */
|
||||
#define CR0_PG BIT(31)
|
||||
/* Enable write protection in supervisor mode */
|
||||
#define CR0_WP BIT(16)
|
||||
/* Enable protected mode */
|
||||
#define CR0_PE BIT(0)
|
||||
|
||||
/**
|
||||
* \brief Enable or disable write protection enforcement in supervisor mode.
|
||||
* When disabled, supervisory code (i.e. code running at ring levels
|
||||
* 0-2) is permitted to write to pages that are marked read-only in
|
||||
* page tables.
|
||||
*
|
||||
* \param en Set to true to enable write protection enforcement.
|
||||
*/
|
||||
static inline void prot_domains_set_wp(bool en)
|
||||
{
|
||||
uint32_t cr0_val = CR0_PG | CR0_PE;
|
||||
if(en) {
|
||||
cr0_val |= CR0_WP;
|
||||
}
|
||||
__asm__ __volatile__ ("mov %0, %%cr0" :: "r"(cr0_val));
|
||||
}
|
||||
|
||||
#endif /* CPU_X86_MM_PAGING_PROT_DOMAINS_H_ */
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_PAGING_H_
|
||||
#define CPU_X86_MM_PAGING_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Page table entry format for PAE mode page table. See Intel Combined Manual,
|
||||
* Vol. 3, Section 4.4 for more details.
|
||||
*/
|
||||
typedef union pte {
|
||||
struct {
|
||||
uint64_t present : 1;
|
||||
uint64_t writable : 1;
|
||||
uint64_t user_accessible : 1;
|
||||
uint64_t pwt : 1; /**< Specify write-through cache policy */
|
||||
uint64_t pcd : 1; /**< Disable caching */
|
||||
uint64_t accessed : 1;
|
||||
uint64_t dirty : 1;
|
||||
uint64_t : 5;
|
||||
uint64_t addr : 51;
|
||||
uint64_t exec_disable : 1;
|
||||
};
|
||||
uint64_t raw;
|
||||
} pte_t;
|
||||
|
||||
#define ENTRIES_PER_PDPT 4
|
||||
#define ENTRIES_PER_PAGE_TABLE 512
|
||||
|
||||
typedef pte_t pdpt_t[ENTRIES_PER_PDPT];
|
||||
typedef pte_t page_table_t[ENTRIES_PER_PAGE_TABLE];
|
||||
|
||||
#define MIN_PAGE_SIZE_SHAMT 12
|
||||
#define MIN_PAGE_SIZE (1 << MIN_PAGE_SIZE_SHAMT)
|
||||
|
||||
#endif /* CPU_X86_MM_PAGING_H_ */
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "prot-domains.h"
|
||||
|
||||
#include "gdt.h"
|
||||
#include <stdio.h>
|
||||
#include "interrupt.h"
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include "syscalls.h"
|
||||
#include "stacks.h"
|
||||
|
||||
static dom_kern_data_t __attribute__((section(".kern_prot_dom_bss")))
|
||||
ATTR_KERN_ADDR_SPACE PROT_DOMAINS_PDCS_NM(kern_dcd);
|
||||
PROT_DOMAINS_ALLOC_IMPL(kern_dcd);
|
||||
static dom_client_data_t ATTR_BSS_KERN kern_dcd;
|
||||
static dom_kern_data_t __attribute__((section(".app_prot_dom_bss")))
|
||||
ATTR_KERN_ADDR_SPACE PROT_DOMAINS_PDCS_NM(app_dcd);
|
||||
PROT_DOMAINS_ALLOC_IMPL(app_dcd);
|
||||
static dom_client_data_t ATTR_BSS_KERN app_dcd;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
prot_domains_init(void)
|
||||
{
|
||||
segment_desc_t desc;
|
||||
|
||||
gdt_lookup(GDT_IDX_CODE_EXC, &desc);
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
|
||||
/* The exception code segment needs to be readable so that the general
|
||||
* protection fault handler can decode instructions, but the interrupt and
|
||||
* user level code segments should not be.
|
||||
*/
|
||||
SEG_SET_FLAG(desc, TYPE, SEG_TYPE_CODE_EX);
|
||||
#endif
|
||||
|
||||
SEG_SET_FLAG(desc, DPL, PRIV_LVL_INT);
|
||||
gdt_insert(GDT_IDX_CODE_INT, desc);
|
||||
|
||||
SEG_SET_FLAG(desc, DPL, PRIV_LVL_USER);
|
||||
gdt_insert(GDT_IDX_CODE, desc);
|
||||
|
||||
PROT_DOMAINS_INIT_ID(kern_dcd);
|
||||
prot_domains_reg(&kern_dcd, 0, 0, 0, 0, true);
|
||||
PROT_DOMAINS_INIT_ID(app_dcd);
|
||||
prot_domains_reg(&app_dcd, 0, 0, 0, 0, false);
|
||||
|
||||
prot_domains_impl_init();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,376 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_PROT_DOMAINS_H_
|
||||
#define CPU_X86_MM_PROT_DOMAINS_H_
|
||||
|
||||
#if !__ASSEMBLER__
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "helpers.h"
|
||||
#endif
|
||||
|
||||
#define X86_CONF_PROT_DOMAINS__NONE 0
|
||||
#define X86_CONF_PROT_DOMAINS__PAGING 1
|
||||
#define X86_CONF_PROT_DOMAINS__TSS 2
|
||||
#define X86_CONF_PROT_DOMAINS__SWSEG 3
|
||||
|
||||
#define X86_CONF_PROT_DOMAINS_MULTI_SEG \
|
||||
((X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS) || \
|
||||
(X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG))
|
||||
|
||||
/** Privilege level (ring) for exception handlers and other supervisory code */
|
||||
#define PRIV_LVL_EXC 0
|
||||
#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE
|
||||
/** Privilege level for interrupt handlers */
|
||||
#define PRIV_LVL_INT 2
|
||||
/** Default privilege level */
|
||||
#define PRIV_LVL_USER 3
|
||||
#else
|
||||
#define PRIV_LVL_INT PRIV_LVL_EXC
|
||||
#define PRIV_LVL_USER PRIV_LVL_EXC
|
||||
#endif
|
||||
|
||||
#define DOM_ID_kern 0
|
||||
#define DOM_ID_app 1
|
||||
|
||||
/** I/O Privilege Level */
|
||||
#define EFLAGS_IOPL(pl) ((pl) << 12)
|
||||
/** Interrupt Enable Flag */
|
||||
#define EFLAGS_IF (1u << 9)
|
||||
|
||||
#if !__ASSEMBLER__
|
||||
|
||||
/** Protection domain ID */
|
||||
typedef uint32_t dom_id_t;
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
|
||||
#include "paging-prot-domains.h"
|
||||
#elif X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS
|
||||
#include "tss-prot-domains.h"
|
||||
#elif X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
|
||||
#include "swseg-prot-domains.h"
|
||||
#endif
|
||||
|
||||
#ifndef ATTR_META_ADDR_SPACE
|
||||
#define ATTR_META_ADDR_SPACE
|
||||
#endif
|
||||
#ifndef ATTR_MMIO_ADDR_SPACE
|
||||
#define ATTR_MMIO_ADDR_SPACE
|
||||
#endif
|
||||
#ifndef ATTR_KERN_ADDR_SPACE
|
||||
#define ATTR_KERN_ADDR_SPACE
|
||||
#endif
|
||||
|
||||
#ifndef MMIO_READL
|
||||
#define MMIO_READL(dst, src) dst = (src)
|
||||
#define MMIO_READW(dst, src) dst = (src)
|
||||
#define MMIO_READB(dst, src) dst = (src)
|
||||
#define MMIO_WRITEL(dst, src) MMIO_READL(dst, src)
|
||||
#define MMIO_WRITEW(dst, src) MMIO_READW(dst, src)
|
||||
#define MMIO_WRITEB(dst, src) MMIO_READB(dst, src)
|
||||
#endif
|
||||
#ifndef KERN_READL
|
||||
#define KERN_READL(dst, src) dst = (src)
|
||||
#define KERN_READW(dst, src) dst = (src)
|
||||
#define KERN_READB(dst, src) dst = (src)
|
||||
#define KERN_WRITEL(dst, src) KERN_READL(dst, src)
|
||||
#define KERN_WRITEW(dst, src) KERN_READW(dst, src)
|
||||
#define KERN_WRITEB(dst, src) KERN_READB(dst, src)
|
||||
#endif
|
||||
#ifndef META_READL
|
||||
#define META_READL(dst, src) dst = (src)
|
||||
#define META_READW(dst, src) dst = (src)
|
||||
#define META_READB(dst, src) dst = (src)
|
||||
#define META_WRITEL(dst, src) META_READL(dst, src)
|
||||
#define META_WRITEW(dst, src) META_READw(dst, src)
|
||||
#define META_WRITEB(dst, src) META_READB(dst, src)
|
||||
#endif
|
||||
|
||||
#ifndef MEMCPY_FROM_META
|
||||
#define MEMCPY_FROM_META(dst, src, sz) \
|
||||
memcpy((void *)(dst), (const void *)(src), (sz))
|
||||
#define MEMCPY_TO_META(dst, src, sz) MEMCPY_FROM_META(dst, src, sz)
|
||||
#endif
|
||||
|
||||
/* The following symbols are defined in the linker script */
|
||||
/** Bounds for .text section */
|
||||
extern uint32_t _stext_addr, _etext_addr;
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE
|
||||
|
||||
/** Metadata that should not be DMA-accessible */
|
||||
#define ATTR_BSS_META __attribute__((section(".meta_bss"))) ATTR_META_ADDR_SPACE
|
||||
/** Kernel-owned data */
|
||||
#define ATTR_BSS_KERN __attribute__((section(".kern_bss"))) ATTR_KERN_ADDR_SPACE
|
||||
/** Code that should only be executable during bootup */
|
||||
#define ATTR_CODE_BOOT __attribute__((section(".boot_text")))
|
||||
|
||||
/**
|
||||
* Domain-defined metadata must be page-aligned, which is implemented by the
|
||||
* linker script for variables with this attribute.
|
||||
*/
|
||||
#define ATTR_BSS_KERN_PAGE_ALIGNED \
|
||||
__attribute__((section(".page_aligned_kern_bss")))
|
||||
|
||||
/** Bounds for .kern_data, .syscall_data, and .prot_dom_data sections */
|
||||
extern uint32_t _sbss_kern_addr, _ebss_kern_addr;
|
||||
/** End of .syscall_data section */
|
||||
extern uint32_t _ebss_syscall_addr;
|
||||
/** Bounds for other data sections */
|
||||
extern uint32_t _sdata_addr, _edata_addr;
|
||||
|
||||
#ifndef SEG_KERN
|
||||
#define SEG_KERN "d"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* If set, this protection domain is already in the call stack and is not
|
||||
* available for nested invocations.
|
||||
*/
|
||||
#define PROT_DOMAINS_FLAG_BUSY BIT(0)
|
||||
/** If set, this protection domain requires port I/O access. */
|
||||
#define PROT_DOMAINS_FLAG_PIO BIT(1)
|
||||
/** If set, this protection domain is initialized. */
|
||||
#define PROT_DOMAINS_FLAG_INITED BIT(2)
|
||||
|
||||
/**
|
||||
* Data associated with each protection domain that should be fully accessible
|
||||
* only to the kernel, with limited accesses and modifications permitted from
|
||||
* other domains. Includes storage for system data structures.
|
||||
*/
|
||||
typedef struct dom_kern_data dom_kern_data_t;
|
||||
|
||||
extern volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE prot_domains_kern_data[];
|
||||
extern volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE prot_domains_kern_data_end[];
|
||||
|
||||
#define PROT_DOMAINS_ACTUAL_CNT \
|
||||
(prot_domains_kern_data_end - prot_domains_kern_data)
|
||||
|
||||
#define PROT_DOMAINS_GET_DOM_ID(dkd) \
|
||||
((dom_id_t)((dkd) - prot_domains_kern_data))
|
||||
|
||||
void prot_domains_syscall_dispatcher(void);
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__TSS
|
||||
/**
|
||||
* Data associated with each protection domain that is owned by clients of that
|
||||
* domain and used to identify the domain.
|
||||
*/
|
||||
struct dom_client_data {
|
||||
dom_id_t dom_id;
|
||||
} __attribute__((packed));
|
||||
#endif
|
||||
|
||||
#ifndef PROT_DOMAINS_ALLOC_IMPL
|
||||
#define PROT_DOMAINS_ALLOC_IMPL(nm)
|
||||
#endif
|
||||
|
||||
/** Allocate the client-owned protection domain data structure. */
|
||||
#define PROT_DOMAINS_PDCS_NM(nm) _pdcs_##nm
|
||||
#define PROT_DOMAINS_ALLOC(typ, nm) \
|
||||
static dom_kern_data_t __attribute__((section(".prot_dom_bss"))) \
|
||||
ATTR_KERN_ADDR_SPACE PROT_DOMAINS_PDCS_NM(nm); \
|
||||
PROT_DOMAINS_ALLOC_IMPL(nm); \
|
||||
static typ ATTR_BSS_KERN nm
|
||||
#define PROT_DOMAINS_INIT_ID(nm) \
|
||||
KERN_WRITEL((nm).dom_id, PROT_DOMAINS_GET_DOM_ID(&PROT_DOMAINS_PDCS_NM(nm)))
|
||||
|
||||
/**
|
||||
* Perform early initialization during boot stage 0 to prepare for boot stage 1
|
||||
*/
|
||||
void prot_domains_gdt_init() ATTR_CODE_BOOT;
|
||||
/**
|
||||
* Perform initialization during boot stage 1 to prepare for kernel launch
|
||||
*/
|
||||
void prot_domains_init();
|
||||
void prot_domains_impl_init();
|
||||
|
||||
/* Return from cpu_boot_stage1 will invoke prot_domains_launch_kernel due to
|
||||
* that return address being pushed on the stack by cpu_boot_stage0.
|
||||
*/
|
||||
#define prot_domains_leave_boot_stage1()
|
||||
|
||||
/* Return from main will invoke prot_domains_launch_app due to that return
|
||||
* address being pushed on the stack by cpu_boot_stage0.
|
||||
*/
|
||||
#define prot_domains_leave_main()
|
||||
|
||||
void prot_domains_launch_kernel(void);
|
||||
|
||||
/* Whenever changing this, update syscalls-int-asm.S:prot_domains_launch_kernel
|
||||
* to match:
|
||||
*/
|
||||
#define PROT_DOMAINS_INIT_RET_ADDR_CNT 2
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS
|
||||
void prot_domains_launch_app(void);
|
||||
#else
|
||||
void app_main(void);
|
||||
#define prot_domains_launch_app app_main
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define ATTR_BSS_META
|
||||
#define ATTR_BSS_KERN
|
||||
#define ATTR_CODE_BOOT
|
||||
|
||||
struct dom_client_data {
|
||||
uintptr_t mmio; /**< MMIO range base address */
|
||||
uintptr_t meta; /**< Domain-defined metadata base address */
|
||||
};
|
||||
|
||||
/** Retrieve the MMIO base address for the specified protection domain. */
|
||||
#define PROT_DOMAINS_MMIO(dcd) ((dcd).mmio)
|
||||
|
||||
/** Retrieve the metadata base address for the specified protection domain. */
|
||||
#define PROT_DOMAINS_META(dcd) ((dcd).meta)
|
||||
|
||||
#define PROT_DOMAINS_ALLOC(typ, nm) static typ nm
|
||||
#define PROT_DOMAINS_INIT_ID(nm)
|
||||
|
||||
#define prot_domains_gdt_init()
|
||||
|
||||
#define prot_domains_init()
|
||||
|
||||
int main(void);
|
||||
#define prot_domains_leave_boot_stage1 main
|
||||
#define prot_domains_leave_main ENABLE_IRQ(); app_main
|
||||
|
||||
#define PROT_DOMAINS_INIT_RET_ADDR_CNT 0
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Protection domain data readable by the client. It is used to control
|
||||
* execution, so it should be protected from modifications by clients.
|
||||
* Otherwise, there is a risk that one client could modify one of these
|
||||
* structures used by another client to issue a system call, which could then
|
||||
* cause the latter client to perform an unintended system call.
|
||||
*/
|
||||
typedef struct dom_client_data dom_client_data_t;
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE
|
||||
#define prot_domains_reg(dcd, mmio_, mmio_sz, meta_, meta_sz, pio) \
|
||||
(dcd)->mmio = (mmio_); \
|
||||
(dcd)->meta = (meta_)
|
||||
#else
|
||||
/**
|
||||
* \brief Register a protection domain, which involves creating the
|
||||
* necessary system data structures for it.
|
||||
*
|
||||
* \param dcd Client-accessible domain information
|
||||
* \param mmio Optional base address for per-domain memory-mapped IO region
|
||||
* \param mmio_sz Size of MMIO region
|
||||
* \param meta Optional base address for per-domain metadata
|
||||
* \param meta_sz Size of metadata
|
||||
* \param pio Set to true if protection domain requires port IO access
|
||||
*/
|
||||
void prot_domains_reg(dom_client_data_t ATTR_KERN_ADDR_SPACE *dcd,
|
||||
uintptr_t mmio,
|
||||
size_t mmio_sz,
|
||||
uintptr_t meta,
|
||||
size_t meta_sz,
|
||||
bool pio);
|
||||
#endif
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE
|
||||
#define prot_domains_copy_dcd(dst, src) *(dst) = *(src)
|
||||
#else
|
||||
static inline void
|
||||
/**
|
||||
* It is necessary to make a local copy of a dom_client_data structure when a
|
||||
* multi-segment protection domain implementation is in use, segment attributes
|
||||
* are not supported by the compiler, and a dom_client_data structure needs to
|
||||
* be passed by value into some function. Otherwise, the compiler will not know
|
||||
* to access the non-default segment in which *src is stored and will attempt
|
||||
* to copy it out of the default data segment.
|
||||
*/
|
||||
prot_domains_copy_dcd(struct dom_client_data *dst,
|
||||
struct dom_client_data ATTR_KERN_ADDR_SPACE *src)
|
||||
{
|
||||
KERN_READL(dst->dom_id, src->dom_id);
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS
|
||||
KERN_READL(dst->tss_sel, src->tss_sel);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !X86_CONF_PROT_DOMAINS_MULTI_SEG
|
||||
#define prot_domains_enable_mmio()
|
||||
#define prot_domains_disable_mmio()
|
||||
|
||||
#define KERN_DATA_OFF_TO_PHYS_ADDR(x) ((uintptr_t)(x))
|
||||
#define DATA_OFF_TO_PHYS_ADDR(x) ((uintptr_t)(x))
|
||||
#endif
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE
|
||||
#define prot_domains_lookup_meta_phys_base(drv) 0
|
||||
#else
|
||||
/** Lookup base physical address of metadata region for specified domain */
|
||||
uintptr_t prot_domains_lookup_meta_phys_base(dom_client_data_t ATTR_KERN_ADDR_SPACE *drv);
|
||||
#endif
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__PAGING
|
||||
#define PROT_DOMAINS_META_OFF_TO_PHYS(off, meta_phys_base) \
|
||||
((meta_phys_base) + (off))
|
||||
#endif
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE
|
||||
#define PROT_DOMAINS_ENTER_ISR(...)
|
||||
#define PROT_DOMAINS_LEAVE_ISR(...)
|
||||
#else
|
||||
#define PROT_DOMAINS_ENTER_ISR_COMMON(exc) \
|
||||
".if !" #exc "\n\t" \
|
||||
/* Save the current stack pointer into a callee-saved register. */ \
|
||||
"mov %%esp, %%ebx\n\t" \
|
||||
/* Pivot to the main stack of the interrupted context. */ \
|
||||
/* Interrupts never have an error code, so the offset is always 44. */ \
|
||||
/* No interrupt handlers use anything from the original interrupt stack, */ \
|
||||
/* so there is no need to copy anything from it to the main stack. */ \
|
||||
"mov 44(%%esp), %%esp\n\t" \
|
||||
".endif\n\t"
|
||||
#define PROT_DOMAINS_LEAVE_ISR_COMMON(exc) \
|
||||
/* Restore the interrupt/exception stack pointer. */ \
|
||||
".if !" #exc "\n\t" \
|
||||
"mov %%ebx, %%esp\n\t" \
|
||||
".endif\n\t"
|
||||
#endif
|
||||
|
||||
#ifdef X86_CONF_PROT_DOMAINS_MULTI_SEG
|
||||
/* include GDT section definitions used when allocating protection domains: */
|
||||
#include "gdt.h"
|
||||
#endif
|
||||
|
||||
#endif /* !__ASSEMBLER__ */
|
||||
|
||||
#endif /* CPU_X86_MM_PROT_DOMAINS_H_ */
|
|
@ -1,146 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_SEGMENTATION_H_
|
||||
#define CPU_X86_MM_SEGMENTATION_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define SEG_FLAG(lbl, val) \
|
||||
(((val) & (~0u >> (32 - SEG_WIDTH_##lbl))) << SEG_SHAMT_##lbl)
|
||||
|
||||
#define SEG_SET_FLAG(desc, lbl, val) \
|
||||
(desc).flags = ((desc).flags & ~SEG_FLAG(lbl, ~0u)) | SEG_FLAG(lbl, val)
|
||||
|
||||
#define SEG_WIDTH_TYPE 4
|
||||
#define SEG_SHAMT_TYPE 0
|
||||
#define SEG_WIDTH_DESCTYPE 1
|
||||
#define SEG_SHAMT_DESCTYPE 4
|
||||
#define SEG_WIDTH_DPL 2
|
||||
#define SEG_SHAMT_DPL 5
|
||||
#define SEG_WIDTH_PRESENT 1
|
||||
#define SEG_SHAMT_PRESENT 7
|
||||
#define SEG_WIDTH_LIMIT_HI 4
|
||||
#define SEG_SHAMT_LIMIT_HI 8
|
||||
#define SEG_WIDTH_AVL 1
|
||||
#define SEG_SHAMT_AVL 12
|
||||
#define SEG_WIDTH_LONG_MODE 1
|
||||
#define SEG_SHAMT_LONG_MODE 13
|
||||
/* also used to indicate default operand and address size */
|
||||
#define SEG_WIDTH_DIRECTION 1
|
||||
#define SEG_SHAMT_DIRECTION 14
|
||||
#define SEG_WIDTH_GRAN 1
|
||||
#define SEG_SHAMT_GRAN 15
|
||||
|
||||
#define SEG_TYPE_DATA_RDONLY SEG_FLAG(TYPE, 0x00) /* Read only */
|
||||
#define SEG_TYPE_DATA_RDWR SEG_FLAG(TYPE, 0x02) /* Read/Write */
|
||||
#define SEG_TYPE_CODE_EXRD SEG_FLAG(TYPE, 0x0A) /* Execute/Read */
|
||||
#define SEG_TYPE_CODE_EX SEG_FLAG(TYPE, 0x08) /* Execute only */
|
||||
#define SEG_TYPE_LDT SEG_FLAG(TYPE, 0x02)
|
||||
#define SEG_TYPE_TSS32_AVAIL SEG_FLAG(TYPE, 0x09)
|
||||
|
||||
#define SEG_DESCTYPE_SYS SEG_FLAG(DESCTYPE, 0)
|
||||
#define SEG_DESCTYPE_NSYS SEG_FLAG(DESCTYPE, 1)
|
||||
|
||||
#define SEG_PRESENT SEG_FLAG(PRESENT, 1)
|
||||
|
||||
#define SEG_DEFL_OPSZ_32BIT SEG_FLAG(DIRECTION, 1)
|
||||
|
||||
#define SEG_GRAN_BYTE SEG_FLAG(GRAN, 0)
|
||||
#define SEG_GRAN_PAGE SEG_FLAG(GRAN, 1)
|
||||
|
||||
/**
|
||||
* Maximum length of segment that can be regulated with a byte-granularity
|
||||
* segment limit.
|
||||
*/
|
||||
#define SEG_MAX_BYTE_GRAN_LEN (1 << 20)
|
||||
|
||||
/**
|
||||
* Segment descriptor. See Intel Combined Manual,
|
||||
* Vol. 3, Section 3.4.5 for more details.
|
||||
*/
|
||||
typedef union segment_desc {
|
||||
struct {
|
||||
uint32_t lim_lo : 16;
|
||||
uint32_t base_lo : 16;
|
||||
uint32_t base_mid : 8;
|
||||
uint32_t flags : 16;
|
||||
uint32_t base_hi : 8;
|
||||
};
|
||||
struct {
|
||||
uint32_t raw_lo, raw_hi;
|
||||
};
|
||||
uint64_t raw;
|
||||
} segment_desc_t;
|
||||
|
||||
#define SEG_DESC_NOT_PRESENT 0
|
||||
|
||||
/* The next two functions are invoked by boot code, so they must always be
|
||||
* inlined to avoid being placed in a different address space than the initial,
|
||||
* flat address space.
|
||||
*/
|
||||
static inline void __attribute__((always_inline))
|
||||
segment_desc_set_limit(segment_desc_t *c_this, uint32_t len)
|
||||
{
|
||||
uint32_t limit = len - 1;
|
||||
|
||||
SEG_SET_FLAG(*c_this, LIMIT_HI, limit >> 16); /* set limit bits 19:16 */
|
||||
c_this->lim_lo = limit; /* set limit bits 15:0 */
|
||||
}
|
||||
/**
|
||||
* \brief Initialize a segment descriptor.
|
||||
* \param c_this Segment descriptor to be initialized.
|
||||
* \param base Base address of region to be covered by segment descriptor.
|
||||
* \param len Length to be specified by segment descriptor. The units may
|
||||
* be bytes or pages, depending on the flags.
|
||||
* \param flags Flags to be added to the default flags: present, default
|
||||
* operand size of 32 bits, and high limit bits.
|
||||
*/
|
||||
static inline void __attribute__((always_inline))
|
||||
segment_desc_init(segment_desc_t *c_this,
|
||||
uint32_t base, uint32_t len, uint16_t flags)
|
||||
{
|
||||
c_this->raw = 0;
|
||||
|
||||
/* Create the high 32 bit segment */
|
||||
c_this->base_mid = base >> 16; /* set base bits 23:16 */
|
||||
c_this->base_hi = base >> 24; /* set base bits 31:24 */
|
||||
|
||||
/* Create the low 32 bit segment */
|
||||
c_this->base_lo = base; /* set base bits 15:0 */
|
||||
|
||||
c_this->flags = SEG_FLAG(PRESENT, 1) | SEG_DEFL_OPSZ_32BIT | flags;
|
||||
|
||||
/* This must be done after setting the other flags, or else it
|
||||
* would be partially overridden.
|
||||
*/
|
||||
segment_desc_set_limit(c_this, len);
|
||||
}
|
||||
#endif /* CPU_X86_MM_SEGMENTATION_H_ */
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "stacks.h"
|
||||
|
||||
uint8_t stacks_main[STACKS_SIZE_MAIN]
|
||||
__attribute__((section(".main_stack"), aligned(4)));
|
||||
#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE
|
||||
uint8_t stacks_int[STACKS_SIZE_INT]
|
||||
__attribute__((section(".int_stack"), aligned(4)));
|
||||
uint8_t stacks_exc[STACKS_SIZE_EXC]
|
||||
__attribute__((section(".exc_stack"), aligned(4)));
|
||||
#endif
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_STACKS_H_
|
||||
#define CPU_X86_MM_STACKS_H_
|
||||
|
||||
#include "prot-domains.h"
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__NONE
|
||||
#define STACKS_SIZE_INT 0
|
||||
#else
|
||||
/**
|
||||
* The necessary amount of space for the interrupt and exception stacks is
|
||||
* determined by the amount of data pushed on the stack by the CPU when
|
||||
* delivering an interrupt or exception, and by the additional data pushed
|
||||
* on the stack by the interrupt dispatcher. See interrupt.h for more details.
|
||||
*/
|
||||
#define STACKS_SIZE_INT (14 * 4)
|
||||
#endif
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
|
||||
/**
|
||||
* The system call and return dispatchers use this stack, so its size was
|
||||
* determined by observing their behavior. It is possible that the dispatchers
|
||||
* could overflow the stack and overwrite data on the other stacks. An
|
||||
* alternative design that would facilitate detection of such overflows would
|
||||
* place the exception handler stack on a separate page surrounded by guard
|
||||
* bands, but that would consume a substantial amount of additional memory.
|
||||
*
|
||||
* All stack sizes should be a multiple of 4 to accommodate a 4-byte alignment.
|
||||
*/
|
||||
#ifdef __clang__
|
||||
#define STACKS_SIZE_EXC 512
|
||||
#else
|
||||
#define STACKS_SIZE_EXC 256
|
||||
#endif
|
||||
#elif X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
|
||||
#ifdef __clang__
|
||||
#define STACKS_SIZE_EXC 512
|
||||
#else
|
||||
#define STACKS_SIZE_EXC 256
|
||||
#endif
|
||||
#elif X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__TSS
|
||||
/**
|
||||
* This should be large enough to execute the exception handler with the
|
||||
* largest stack requirement: double_fault_handler:
|
||||
* - 1 word for the return address from calling double_fault_handler
|
||||
* - 1 word for the saved frame pointer in double_fault_handler
|
||||
* - 2 words that GCC has been observed to skip on the stack to align it
|
||||
* to a preferred boundary
|
||||
* - 1 word for the return address for calling halt
|
||||
*/
|
||||
#define STACKS_SIZE_EXC (STACKS_SIZE_INT + (6 * 4))
|
||||
#else
|
||||
#define STACKS_SIZE_EXC STACKS_SIZE_INT
|
||||
#endif
|
||||
/**
|
||||
* The combined size of the stacks should be an even multiple of the 4K page
|
||||
* size so that they precisely fill some number of pages when paging-based
|
||||
* protection domains are in use. The stacks are arranged contiguously by
|
||||
* the linker scripts. See those and README.md for more details.
|
||||
*/
|
||||
#define STACKS_SIZE_MAIN (8192 - (STACKS_SIZE_INT + STACKS_SIZE_EXC))
|
||||
|
||||
#if !__ASSEMBLER__
|
||||
/**
|
||||
* Stack for exception handlers. Also used for system call and return
|
||||
* dispatchers when paging-based protection domains are enabled.
|
||||
*/
|
||||
extern uint8_t stacks_exc[STACKS_SIZE_EXC];
|
||||
/** Stack for interrupt handlers. */
|
||||
extern uint8_t stacks_int[STACKS_SIZE_INT];
|
||||
/** Main C stack. */
|
||||
extern uint8_t stacks_main[STACKS_SIZE_MAIN];
|
||||
|
||||
#define STACKS_INIT_TOP \
|
||||
((uintptr_t)stacks_main + STACKS_SIZE_MAIN - \
|
||||
(PROT_DOMAINS_INIT_RET_ADDR_CNT * sizeof(uintptr_t)))
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CPU_X86_MM_STACKS_H_ */
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gdt.h"
|
||||
#include "helpers.h"
|
||||
#include "multi-segment.h"
|
||||
#include "prot-domains.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
prot_domains_reg(dom_client_data_t ATTR_KERN_ADDR_SPACE *dcd,
|
||||
uintptr_t mmio, size_t mmio_sz,
|
||||
uintptr_t meta, size_t meta_sz,
|
||||
bool pio)
|
||||
{
|
||||
volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *dkd;
|
||||
dom_id_t dom_id;
|
||||
|
||||
KERN_READL(dom_id, dcd->dom_id);
|
||||
|
||||
if(PROT_DOMAINS_ACTUAL_CNT <= dom_id) {
|
||||
halt();
|
||||
}
|
||||
|
||||
dkd = prot_domains_kern_data + dom_id;
|
||||
|
||||
prot_domains_reg_multi_seg(dkd, mmio, mmio_sz, meta, meta_sz);
|
||||
|
||||
KERN_WRITEL(dkd->flags, pio ? PROT_DOMAINS_FLAG_PIO : 0);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static inline void __attribute__((always_inline))
|
||||
prot_domains_switch(dom_id_t from_id, dom_id_t to_id,
|
||||
interrupt_stack_t *intr_stk)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"lldt %[_ldt_]\n\t"
|
||||
"mov %[_meta_seg_], %%eax\n\t"
|
||||
"lsl %%eax, %%ecx\n\t"
|
||||
"jz 1f\n\t" /* ZF will only be set if the segment descriptor is valid. */
|
||||
"xor %%eax, %%eax\n\t" /* Nullify metadata selector */
|
||||
"1: mov %%eax, %%" SEG_META "s\n\t"
|
||||
"mov %[_kern_seg_], %%eax\n\t"
|
||||
"mov %%eax, %%" SEG_KERN "s\n\t"
|
||||
:
|
||||
: [_ldt_] "r" ((uint16_t)GDT_SEL_LDT(to_id)),
|
||||
[_meta_seg_] "i" (LDT_SEL_META),
|
||||
[_kern_seg_] "i" (LDT_SEL_KERN)
|
||||
: "cc", "eax", "ecx"
|
||||
);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Enable inter-procedural optimization with procedures in the following file:
|
||||
*/
|
||||
#include "syscalls-int.c"
|
|
@ -1,86 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_SWSEG_PROT_DOMAINS_H_
|
||||
#define CPU_X86_MM_SWSEG_PROT_DOMAINS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include "ldt-layout.h"
|
||||
#include "paging.h"
|
||||
#include "segmentation.h"
|
||||
#include "syscalls-int.h"
|
||||
|
||||
struct dom_kern_data {
|
||||
/** Local Descriptor Table with per-domain descriptors */
|
||||
segment_desc_t ldt[LDT_NUM_DESC];
|
||||
/** Flags are defined with the prefix PROT_DOMAINS_FLAG in prot-domains.h */
|
||||
uint32_t flags;
|
||||
/**
|
||||
* Original return address from call stack when this protection domain
|
||||
* invoked some other protection domain. This serves to control the return
|
||||
* entrypoint. The callee is not permitted to modify this value (unless the
|
||||
* callee is the kernel protection domain).
|
||||
*/
|
||||
uintptr_t orig_ret_addr;
|
||||
|
||||
/* This structure is precisely 32 bytes in length, a power of 2. If its size
|
||||
* changes, add an alignment attribute to keep it aligned at a power of 2 so
|
||||
* that dereferencing arrays of these structures uses shift instructions
|
||||
* instead of multiplication. Shifting is faster than multiplication.
|
||||
*/
|
||||
};
|
||||
|
||||
/* relies on dom_kern_data: */
|
||||
#include "multi-segment.h"
|
||||
|
||||
#define PROT_DOMAINS_ENTER_ISR(exc) \
|
||||
MULTI_SEGMENT_ENTER_ISR(exc) \
|
||||
PROT_DOMAINS_ENTER_ISR_COMMON(exc)
|
||||
#define PROT_DOMAINS_LEAVE_ISR(exc) \
|
||||
PROT_DOMAINS_LEAVE_ISR_COMMON(exc) \
|
||||
MULTI_SEGMENT_LEAVE_ISR(exc)
|
||||
|
||||
#define prot_domains_impl_init syscalls_int_init
|
||||
|
||||
#define prot_domains_set_wp(en)
|
||||
|
||||
/* Allocate one additional GDT entry for each protection domain. Note that
|
||||
* the particular storage allocated by this statement may actually be used for
|
||||
* some other protection domain, depending on how the linker happens to arrange
|
||||
* all of the GDT storage. The GDT_IDX_LDT macro in gdt-layout.h determine
|
||||
* which storage is used for each protection domain. Thus, this storage should
|
||||
* not be referenced directly by its variable name.
|
||||
*/
|
||||
#define PROT_DOMAINS_ALLOC_IMPL(nm) \
|
||||
static segment_desc_t ATTR_BSS_GDT_MID _gdt_storage_##nm
|
||||
|
||||
#endif /* CPU_X86_MM_SWSEG_PROT_DOMAINS_H_ */
|
|
@ -1,133 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "syscalls-int.h"
|
||||
#include "prot-domains.h"
|
||||
#include "gdt-layout.h"
|
||||
#include "stacks.h"
|
||||
|
||||
/* Must match definitions (plus the trailing 's') in multi-segment.h */
|
||||
#define SEG_MMIO fs
|
||||
#define SEG_KERN fs
|
||||
|
||||
.text
|
||||
|
||||
/* Invoke the system call return dispatcher from the default privilege
|
||||
* level
|
||||
*/
|
||||
.global prot_domains_sysret_stub
|
||||
prot_domains_sysret_stub:
|
||||
int $PROT_DOMAINS_SYSRET_DISPATCH_INT
|
||||
|
||||
.macro save_segs
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
|
||||
/* Save (and restore, in restore_segs) MMIO segment register into
|
||||
* callee-saved register in case a system call was invoked from a region in
|
||||
* which MMIO is enabled.
|
||||
*/
|
||||
push %SEG_MMIO
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro restore_segs
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
|
||||
pop %SEG_MMIO
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/* Refresh most of the segment registers in case they were corrupted by
|
||||
* userspace code to prevent that from corrupting the operation of the
|
||||
* privileged code.
|
||||
*/
|
||||
.macro load_kern_segs
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
|
||||
mov $GDT_SEL_DATA, %eax
|
||||
mov %eax, %ds
|
||||
mov %eax, %es
|
||||
mov $GDT_SEL_DATA_KERN_EXC, %eax
|
||||
mov %eax, %SEG_KERN
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/* Invoke the system call dispatcher C routine */
|
||||
.global prot_domains_syscall_dispatcher
|
||||
prot_domains_syscall_dispatcher:
|
||||
mov %esp, %ecx /*< interrupt_stack_t *intr_stk */
|
||||
/* EDX already set to "dom_client_data_t to_dcd" by syscall stub */
|
||||
save_segs
|
||||
push %eax /*< syscalls_entrypoint_t *syscall */
|
||||
load_kern_segs
|
||||
call prot_domains_syscall_dispatcher_impl
|
||||
/* fastcall convention, so callee pops arguments */
|
||||
restore_segs
|
||||
iret
|
||||
|
||||
/* Invoke the system call return dispatcher C routine */
|
||||
.global prot_domains_sysret_dispatcher
|
||||
prot_domains_sysret_dispatcher:
|
||||
mov %esp, %ecx /*< interrupt_stack_t *intr_stk */
|
||||
save_segs
|
||||
load_kern_segs
|
||||
call prot_domains_sysret_dispatcher_impl
|
||||
restore_segs
|
||||
/* Zero caller-saved registers in case they contain secrets. The system call
|
||||
* handlers and dispatchers need to preserve the callee-saved registers.
|
||||
*/
|
||||
xor %eax, %eax
|
||||
xor %ecx, %ecx
|
||||
xor %edx, %edx
|
||||
iret
|
||||
|
||||
.global prot_domains_launch_kernel
|
||||
prot_domains_launch_kernel:
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
|
||||
mov $GDT_SEL_DATA, %eax
|
||||
mov %eax, %ds
|
||||
mov %eax, %es
|
||||
mov %eax, %fs
|
||||
mov %eax, %gs
|
||||
#else
|
||||
mov $GDT_SEL_LDT(DOM_ID_kern), %eax
|
||||
lldt %ax
|
||||
call multi_segment_launch_kernel
|
||||
#endif
|
||||
/* init interrupt return stack: */
|
||||
pushl $GDT_SEL_STK
|
||||
lea stacks_main, %eax
|
||||
/* matches STACKS_INIT_TOP, plus 4 since an address has been consumed: */
|
||||
add $(STACKS_SIZE_MAIN - 4), %eax
|
||||
pushl %eax
|
||||
pushl $EFLAGS_IOPL(PRIV_LVL_INT)
|
||||
pushl $GDT_SEL_CODE
|
||||
pushl $0 /* will be overwritten by syscall_dispatcher_impl */
|
||||
/* fastcall convention: */
|
||||
mov %esp, %ecx
|
||||
call prot_domains_launch_kernel_impl
|
||||
iretl
|
|
@ -1,318 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "prot-domains.h"
|
||||
#include "tss.h"
|
||||
#include "helpers.h"
|
||||
#include "stacks.h"
|
||||
#include "idt.h"
|
||||
#include "syscalls.h"
|
||||
#include "gdt.h"
|
||||
#include "gdt-layout.h"
|
||||
#include "interrupt.h"
|
||||
|
||||
/**
|
||||
* Current protection domain. Not protected, since it is just a convenience
|
||||
* variable to avoid unneeded protection domain switches.
|
||||
*/
|
||||
dom_id_t cur_dom = DOM_ID_app;
|
||||
|
||||
/* defined in syscalls-int-asm.S */
|
||||
void prot_domains_sysret_dispatcher(void);
|
||||
|
||||
/* Maximum depth of inter-domain call stack */
|
||||
#define MAX_INTER_DOM_CALL_STK_SZ 4
|
||||
|
||||
/* Protected call stack for inter-domain system calls. The stack grows up. */
|
||||
static volatile dom_id_t ATTR_BSS_KERN
|
||||
inter_dom_call_stk[MAX_INTER_DOM_CALL_STK_SZ];
|
||||
|
||||
/* Pointer to the next (free) slot in the inter-domain call stack */
|
||||
static int ATTR_BSS_KERN inter_dom_call_stk_ptr;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static inline void __attribute__((always_inline))
|
||||
update_eflags(dom_id_t from_id, dom_id_t to_id, interrupt_stack_t *intr_stk)
|
||||
{
|
||||
if((to_id == DOM_ID_app) &&
|
||||
(DT_SEL_GET_RPL(intr_stk->cs) == PRIV_LVL_USER)) {
|
||||
/* Only enable interrupts in the application protection domain cooperative
|
||||
* scheduling context.
|
||||
*/
|
||||
intr_stk->eflags |= EFLAGS_IF;
|
||||
} else {
|
||||
intr_stk->eflags &= ~EFLAGS_IF;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static inline void __attribute__((always_inline))
|
||||
dispatcher_tail(dom_id_t from_id, dom_id_t to_id, interrupt_stack_t *intr_stk)
|
||||
{
|
||||
cur_dom = to_id;
|
||||
|
||||
prot_domains_switch(from_id, to_id, intr_stk);
|
||||
|
||||
prot_domains_set_wp(true);
|
||||
|
||||
update_eflags(from_id, to_id, intr_stk);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int main(void);
|
||||
static inline void __attribute__((always_inline))
|
||||
syscall_dispatcher_tail(interrupt_stack_t *intr_stk,
|
||||
dom_id_t to_id,
|
||||
uint32_t syscall_eip)
|
||||
{
|
||||
dom_id_t from_id;
|
||||
uint32_t tmp;
|
||||
volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *from_dkd, *to_dkd;
|
||||
|
||||
uint32_t loc_call_stk_ptr;
|
||||
|
||||
to_dkd = prot_domains_kern_data + to_id;
|
||||
|
||||
/* This implementation of protection domains is non-reentrant. For example,
|
||||
* it stores the return address taken from the stack of a caller domain
|
||||
* while dispatching a system call and stores it in a single field in the
|
||||
* kernel data associated with that protection domain. That model does not
|
||||
* permit reentrancy.
|
||||
*/
|
||||
KERN_READL(tmp, to_dkd->flags);
|
||||
if((tmp & PROT_DOMAINS_FLAG_BUSY) == PROT_DOMAINS_FLAG_BUSY) {
|
||||
halt();
|
||||
}
|
||||
tmp |= PROT_DOMAINS_FLAG_BUSY;
|
||||
KERN_WRITEL(to_dkd->flags, tmp);
|
||||
|
||||
/* Update the interrupt stack so that the IRET instruction will return to the
|
||||
* system call entrypoint.
|
||||
*/
|
||||
intr_stk->eip = syscall_eip;
|
||||
|
||||
KERN_READL(loc_call_stk_ptr, inter_dom_call_stk_ptr);
|
||||
/* Lookup the information for the caller */
|
||||
KERN_READL(from_id, inter_dom_call_stk[loc_call_stk_ptr - 1]);
|
||||
from_dkd = prot_domains_kern_data + from_id;
|
||||
|
||||
/* Save the current return address from the unprivileged stack to a protected
|
||||
* location in the kernel-owned data structure. This enforces return
|
||||
* entrypoint control.
|
||||
*/
|
||||
KERN_WRITEL(from_dkd->orig_ret_addr, *(uintptr_t *)intr_stk->esp);
|
||||
/* Update the unprivileged stack so that when the system call body is
|
||||
* complete, it will invoke the system call return stub.
|
||||
*/
|
||||
*((uintptr_t *)intr_stk->esp) = (uintptr_t)prot_domains_sysret_stub;
|
||||
|
||||
if(MAX_INTER_DOM_CALL_STK_SZ <= loc_call_stk_ptr) {
|
||||
halt();
|
||||
}
|
||||
KERN_WRITEL(inter_dom_call_stk[loc_call_stk_ptr], to_id);
|
||||
|
||||
loc_call_stk_ptr++;
|
||||
KERN_WRITEL(inter_dom_call_stk_ptr, loc_call_stk_ptr);
|
||||
|
||||
dispatcher_tail(from_id, to_id, intr_stk);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void __attribute__((fastcall))
|
||||
prot_domains_syscall_dispatcher_impl(interrupt_stack_t *intr_stk,
|
||||
dom_id_t to_id,
|
||||
syscalls_entrypoint_t *syscall)
|
||||
{
|
||||
uint32_t tmp;
|
||||
uint32_t syscall_eip;
|
||||
|
||||
if(PROT_DOMAINS_ACTUAL_CNT <= to_id) {
|
||||
halt();
|
||||
}
|
||||
|
||||
/* Get the approved entrypoint for the system call being invoked */
|
||||
|
||||
if(!((((uintptr_t)syscalls_entrypoints) <= (uintptr_t)syscall) &&
|
||||
(((uintptr_t)syscall) < (uintptr_t)syscalls_entrypoints_end) &&
|
||||
(((((uintptr_t)syscall) - (uintptr_t)syscalls_entrypoints)
|
||||
% sizeof(syscalls_entrypoint_t)) == 0))) {
|
||||
/* Assert is not usable when switching protection domains */
|
||||
halt();
|
||||
}
|
||||
|
||||
KERN_READL(tmp, syscall->doms);
|
||||
if((BIT(to_id) & tmp) == 0) {
|
||||
halt();
|
||||
}
|
||||
|
||||
KERN_READL(syscall_eip, syscall->entrypoint);
|
||||
|
||||
prot_domains_set_wp(false);
|
||||
|
||||
syscall_dispatcher_tail(intr_stk, to_id, syscall_eip);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int main(void);
|
||||
void __attribute__((fastcall))
|
||||
prot_domains_launch_kernel_impl(interrupt_stack_t *intr_stk)
|
||||
{
|
||||
KERN_WRITEL(inter_dom_call_stk[0], DOM_ID_app);
|
||||
|
||||
KERN_WRITEL(inter_dom_call_stk_ptr, 1);
|
||||
|
||||
syscall_dispatcher_tail(intr_stk, DOM_ID_kern, (uint32_t)main);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void __attribute__((fastcall))
|
||||
prot_domains_sysret_dispatcher_impl(interrupt_stack_t *intr_stk)
|
||||
{
|
||||
dom_id_t from_id, to_id;
|
||||
uint32_t loc_call_stk_ptr;
|
||||
uint32_t flags;
|
||||
|
||||
KERN_READL(loc_call_stk_ptr, inter_dom_call_stk_ptr);
|
||||
if(loc_call_stk_ptr <= 1) {
|
||||
halt();
|
||||
}
|
||||
|
||||
KERN_READL(from_id, inter_dom_call_stk[loc_call_stk_ptr - 1]);
|
||||
KERN_READL(to_id, inter_dom_call_stk[loc_call_stk_ptr - 2]);
|
||||
|
||||
KERN_READL(intr_stk->eip,
|
||||
prot_domains_kern_data[to_id].orig_ret_addr);
|
||||
|
||||
prot_domains_set_wp(false);
|
||||
|
||||
KERN_READL(flags, prot_domains_kern_data[from_id].flags);
|
||||
flags &= ~PROT_DOMAINS_FLAG_BUSY;
|
||||
KERN_WRITEL(prot_domains_kern_data[from_id].flags, flags);
|
||||
|
||||
KERN_WRITEL(inter_dom_call_stk_ptr, loc_call_stk_ptr - 1);
|
||||
|
||||
dispatcher_tail(from_id, to_id, intr_stk);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Lookup the current protection domain.
|
||||
* \return Kernel data structure for the current protection domain.
|
||||
*/
|
||||
static volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *
|
||||
get_current_domain(void)
|
||||
{
|
||||
uint32_t loc_call_stk_ptr;
|
||||
dom_id_t id;
|
||||
KERN_READL(loc_call_stk_ptr, inter_dom_call_stk_ptr);
|
||||
KERN_READL(id, inter_dom_call_stk[loc_call_stk_ptr - 1]);
|
||||
return prot_domains_kern_data + id;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Check whether the protection domain is authorized to perform port
|
||||
* I/O from the cooperative scheduling context.
|
||||
* \param dkd Protection domain to check
|
||||
* \return Result of the check as a Boolean value
|
||||
*/
|
||||
static bool
|
||||
needs_port_io(volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *dkd)
|
||||
{
|
||||
uint32_t dkd_flags;
|
||||
KERN_READL(dkd_flags, dkd->flags);
|
||||
return (dkd_flags & PROT_DOMAINS_FLAG_PIO) == PROT_DOMAINS_FLAG_PIO;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Mark the context parameter as volatile so that writes to it will not get
|
||||
* optimized out. This parameter is not handled like ordinary function
|
||||
* parameters. It actually partially includes the contents of the exception
|
||||
* stack, so updates to those locations can affect the operation of the
|
||||
* subsequent interrupt return.
|
||||
*/
|
||||
static void
|
||||
gp_fault_handler(volatile struct interrupt_context context)
|
||||
{
|
||||
uint32_t cs_lim;
|
||||
uint8_t opcode;
|
||||
|
||||
volatile dom_kern_data_t ATTR_KERN_ADDR_SPACE *dkd = get_current_domain();
|
||||
if (needs_port_io(dkd)) {
|
||||
__asm__ __volatile__ (
|
||||
"mov %%cs, %0\n\t"
|
||||
"lsl %0, %0\n\t"
|
||||
: "=r"(cs_lim));
|
||||
|
||||
if (cs_lim < context.eip) {
|
||||
halt();
|
||||
}
|
||||
|
||||
/* Load first byte of faulting instruction */
|
||||
__asm__ __volatile__ (
|
||||
"movb %%cs:%1, %0"
|
||||
: "=q"(opcode)
|
||||
: "m"(*(uint8_t *)context.eip));
|
||||
|
||||
switch (opcode) {
|
||||
case 0xEC: /* inb */
|
||||
context.eax = (context.eax & ~0xFF) | inb((uint16_t)context.edx);
|
||||
break;
|
||||
case 0xED: /* inl */
|
||||
context.eax = inl((uint16_t)context.edx);
|
||||
break;
|
||||
case 0xEE: /* outb */
|
||||
outb((uint16_t)context.edx, (uint8_t)context.eax);
|
||||
break;
|
||||
case 0xEF: /* outl */
|
||||
outl((uint16_t)context.edx, context.eax);
|
||||
break;
|
||||
default:
|
||||
halt();
|
||||
}
|
||||
|
||||
/* Skip the faulting port I/O instruction that was emulated. */
|
||||
context.eip++;
|
||||
} else {
|
||||
halt();
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
syscalls_int_init(void)
|
||||
{
|
||||
tss_init();
|
||||
|
||||
SET_EXCEPTION_HANDLER(13, 1, gp_fault_handler);
|
||||
|
||||
/* Register system call dispatchers: */
|
||||
|
||||
idt_set_intr_gate_desc(PROT_DOMAINS_SYSCALL_DISPATCH_INT,
|
||||
(uint32_t)prot_domains_syscall_dispatcher,
|
||||
GDT_SEL_CODE_EXC,
|
||||
PRIV_LVL_USER);
|
||||
idt_set_intr_gate_desc(PROT_DOMAINS_SYSRET_DISPATCH_INT,
|
||||
(uint32_t)prot_domains_sysret_dispatcher,
|
||||
GDT_SEL_CODE_EXC,
|
||||
PRIV_LVL_USER);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,109 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_SYSCALLS_INT_H_
|
||||
#define CPU_X86_MM_SYSCALLS_INT_H_
|
||||
|
||||
/** Software interrupt number for dispatching a system call */
|
||||
#define PROT_DOMAINS_SYSCALL_DISPATCH_INT 100
|
||||
/** Software interrupt number for returning from a system call */
|
||||
#define PROT_DOMAINS_SYSRET_DISPATCH_INT 101
|
||||
|
||||
#if !__ASSEMBLER__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern dom_id_t cur_dom;
|
||||
|
||||
#define SYSCALLS_STUB_EPILOGUE(nm) \
|
||||
/* Load the system call identifier into EAX, as required by */ \
|
||||
/* prot_domains_syscall_dispatcher: */ \
|
||||
" mov $" EXP_STRINGIFY(_syscall_ent_##nm) ", %eax\n\t" \
|
||||
/* Check whether the server protection domain is already active: */ \
|
||||
" cmp %edx, cur_dom\n\t" \
|
||||
/* If so, skip the system call dispatcher and directly invoke the */ \
|
||||
/* system call body: */ \
|
||||
" je _syscall_" #nm "\n\t" \
|
||||
" int $" EXP_STRINGIFY(PROT_DOMAINS_SYSCALL_DISPATCH_INT) "\n\t"
|
||||
|
||||
#define SYSCALLS_STUB(nm) \
|
||||
SYSCALLS_ALLOC_ENTRYPOINT(nm); \
|
||||
asm ( \
|
||||
".text\n\t" \
|
||||
".global " #nm "\n\t" \
|
||||
#nm ":\n\t" \
|
||||
/* First, load server protection domain ID into EDX, as required by */ \
|
||||
/* prot_domains_syscall_dispatcher: */ \
|
||||
/* Skip past return address on stack to obtain address of protection */ \
|
||||
/* domain ID parameter: */ \
|
||||
" mov 4(%esp), %edx\n\t" \
|
||||
SYSCALLS_STUB_EPILOGUE(nm))
|
||||
|
||||
#define SYSCALLS_STUB_SINGLETON(nm, dcd) \
|
||||
SYSCALLS_ALLOC_ENTRYPOINT(nm); \
|
||||
asm ( \
|
||||
".text\n\t" \
|
||||
".global " #nm "\n\t" \
|
||||
#nm ":\n\t" \
|
||||
/* First, load server protection domain ID into EDX, as required by */ \
|
||||
/* prot_domains_syscall_dispatcher: */ \
|
||||
" mov %" SEG_KERN "s:" #dcd ", %edx\n\t" \
|
||||
SYSCALLS_STUB_EPILOGUE(nm))
|
||||
|
||||
void syscalls_int_init(void);
|
||||
|
||||
void prot_domains_sysret_stub(void);
|
||||
|
||||
/* Inter-privilege level interrupt stack with no error code. */
|
||||
typedef struct interrupt_stack {
|
||||
uint32_t eip;
|
||||
uint32_t cs;
|
||||
uint32_t eflags;
|
||||
uint32_t esp;
|
||||
uint32_t ss;
|
||||
} interrupt_stack_t;
|
||||
|
||||
#if 0
|
||||
/* Declaration only included for documentation purposes: */
|
||||
/**
|
||||
* \brief Switch to a different protection domain.
|
||||
* \param from_id Origin protection domain.
|
||||
* \param to_id Destination protection domain.
|
||||
* \return Segment selector for kernel data access (only used for
|
||||
* multi-segment implementations).
|
||||
*/
|
||||
uint32_t prot_domains_switch(dom_id_t from_id,
|
||||
dom_id_t to_id,
|
||||
interrupt_stack_t *intr_stk);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CPU_X86_MM_SYSCALLS_INT_H_ */
|
|
@ -1,142 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_SYSCALLS_H_
|
||||
#define CPU_X86_MM_SYSCALLS_H_
|
||||
|
||||
#include "helpers.h"
|
||||
#include "prot-domains.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef uint32_t dom_id_bitmap_t;
|
||||
|
||||
typedef struct syscalls_entrypoint {
|
||||
uintptr_t entrypoint;
|
||||
dom_id_bitmap_t doms;
|
||||
} syscalls_entrypoint_t;
|
||||
extern syscalls_entrypoint_t ATTR_KERN_ADDR_SPACE syscalls_entrypoints[];
|
||||
extern syscalls_entrypoint_t ATTR_KERN_ADDR_SPACE syscalls_entrypoints_end[];
|
||||
|
||||
#define SYSCALLS_ACTUAL_CNT (syscalls_entrypoints_end - syscalls_entrypoints)
|
||||
|
||||
#if X86_CONF_PROT_DOMAINS != X86_CONF_PROT_DOMAINS__NONE
|
||||
|
||||
#define SYSCALLS_ALLOC_ENTRYPOINT(nm) \
|
||||
syscalls_entrypoint_t __attribute__((section(".syscall_bss"))) \
|
||||
ATTR_KERN_ADDR_SPACE _syscall_ent_##nm
|
||||
|
||||
#define SYSCALLS_INIT(nm) \
|
||||
KERN_WRITEL(_syscall_ent_##nm.entrypoint, (uintptr_t)_syscall_##nm); \
|
||||
KERN_WRITEL(_syscall_ent_##nm.doms, 0)
|
||||
|
||||
#define SYSCALLS_DEFINE(nm, ...) \
|
||||
void _syscall_##nm(__VA_ARGS__); \
|
||||
SYSCALLS_STUB(nm); \
|
||||
void _syscall_##nm(__VA_ARGS__)
|
||||
|
||||
#define SYSCALLS_DEFINE_SINGLETON(nm, dcd, ...) \
|
||||
void _syscall_##nm(__VA_ARGS__); \
|
||||
SYSCALLS_STUB_SINGLETON(nm, dcd); \
|
||||
void _syscall_##nm(__VA_ARGS__)
|
||||
|
||||
#define SYSCALLS_AUTHZ_UPD(nm, drv, set) \
|
||||
{ \
|
||||
dom_id_t _sc_tmp_id; \
|
||||
dom_id_bitmap_t _sc_tmp_bm; \
|
||||
KERN_READL(_sc_tmp_id, (drv).dom_id); \
|
||||
KERN_READL(_sc_tmp_bm, _syscall_ent_##nm.doms); \
|
||||
if(set) { \
|
||||
_sc_tmp_bm |= BIT(_sc_tmp_id); \
|
||||
} else { \
|
||||
_sc_tmp_bm &= ~BIT(_sc_tmp_id); \
|
||||
} \
|
||||
KERN_WRITEL(_syscall_ent_##nm.doms, _sc_tmp_bm); \
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that any untrusted pointer that could have been influenced by a caller
|
||||
* (i.e. a stack parameter or global variable) refers to a location at or above
|
||||
* a certain stack boundary and halt otherwise. This is used to prevent a
|
||||
* protection domain from calling a different protection domain and passing a
|
||||
* pointer that references a location in the callee's stack other than its
|
||||
* parameters.
|
||||
*
|
||||
* This also checks that the pointer is either within the stack region or the
|
||||
* shared data region, which is important for preventing redirection of data
|
||||
* accesses to MMIO or metadata regions. This check is omitted for multi-
|
||||
* segment protection domain implementations, since the segment settings
|
||||
* already enforce this property for pointers dereferenced in DS. Pointers
|
||||
* that can be influenced by a caller should not be dereferenced in any other
|
||||
* segment.
|
||||
*
|
||||
* The pointer is both validated and copied to a new storage location, which
|
||||
* must be within the callee's local stack region (excluding the parameter
|
||||
* region). This is to mitigate scenarios such as two pointers being validated
|
||||
* and an adversary later inducing a write through one of the pointers to the
|
||||
* other pointer to corrupt the latter pointer before it is used.
|
||||
*
|
||||
* The frame address is adjusted to account for the first word pushed on the
|
||||
* local frame and the return address, since neither of those should ever be
|
||||
* referenced by an incoming pointer. In particular, if an incoming pointer
|
||||
* references the return address, it could potentially redirect execution with
|
||||
* the privileges of the callee protection domain.
|
||||
*/
|
||||
#if X86_CONF_PROT_DOMAINS_MULTI_SEG
|
||||
#define PROT_DOMAINS_VALIDATE_PTR(validated, untrusted, sz) \
|
||||
validated = untrusted; \
|
||||
if(((uintptr_t)(validated)) < \
|
||||
((2 * sizeof(uintptr_t)) + (uintptr_t)__builtin_frame_address(0))) { \
|
||||
halt(); \
|
||||
}
|
||||
#else
|
||||
#define PROT_DOMAINS_VALIDATE_PTR(validated, untrusted, sz) \
|
||||
validated = untrusted; \
|
||||
if((((uintptr_t)(validated)) < \
|
||||
((2 * sizeof(uintptr_t)) + (uintptr_t)__builtin_frame_address(0))) || \
|
||||
(((uintptr_t)&_edata_addr) <= (((uintptr_t)(validated)) + (sz)))) { \
|
||||
halt(); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#define SYSCALLS_ALLOC_ENTRYPOINT(nm)
|
||||
#define SYSCALLS_INIT(nm)
|
||||
#define SYSCALLS_DEFINE(nm, ...) void nm(__VA_ARGS__)
|
||||
#define SYSCALLS_DEFINE_SINGLETON(nm, dcd, ...) void nm(__VA_ARGS__)
|
||||
#define SYSCALLS_AUTHZ_UPD(nm, drv, set)
|
||||
#define PROT_DOMAINS_VALIDATE_PTR(validated, untrusted, sz) validated = untrusted
|
||||
|
||||
#endif
|
||||
|
||||
#define SYSCALLS_AUTHZ(nm, drv) SYSCALLS_AUTHZ_UPD(nm, drv, true)
|
||||
#define SYSCALLS_DEAUTHZ(nm, drv) SYSCALLS_AUTHZ_UPD(nm, drv, false)
|
||||
|
||||
#endif /* CPU_X86_MM_SYSCALLS_H_ */
|
|
@ -1,88 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
.text
|
||||
|
||||
/* Initialize the TSS fields in prot_domains_reg accordingly:
|
||||
* Note: Each of these must be a callee-saved register, so that they are
|
||||
* restored to their original values prior to the task returning. This will
|
||||
* result in the same values being loaded when the task is next invoked.
|
||||
*/
|
||||
#define CUR_DOM_ID_BITMAP esi
|
||||
|
||||
/* Must match SEG_KERN (plus the trailing 's') in multi-segment.h */
|
||||
#define SEG_KERN fs
|
||||
|
||||
.global prot_domains_syscall_dispatcher
|
||||
prot_domains_syscall_dispatcher:
|
||||
#define PROT_DOMAINS_SYSCALL eax
|
||||
mov prot_domains_syscall, %PROT_DOMAINS_SYSCALL
|
||||
cmp $syscalls_entrypoints, %PROT_DOMAINS_SYSCALL
|
||||
jl halt
|
||||
cmp $syscalls_entrypoints_end, %PROT_DOMAINS_SYSCALL
|
||||
jnl halt
|
||||
#define SYSCALLS_ENTRYPOINTS_ALIGN_MASK ebp
|
||||
mov $3, %SYSCALLS_ENTRYPOINTS_ALIGN_MASK
|
||||
and %PROT_DOMAINS_SYSCALL, %SYSCALLS_ENTRYPOINTS_ALIGN_MASK
|
||||
jnz halt
|
||||
|
||||
/* Compare allowed domains bitmask against current domain ID bitmap. If
|
||||
* the check fails, then the current domain ID bitmap value will be zeroed
|
||||
* out, which could cause incorrect behavior in the future. However, the
|
||||
* response to a failed check is to halt the system, so destroying the
|
||||
* current domain ID bitmap value will have no effect.
|
||||
*/
|
||||
and %SEG_KERN:4(%PROT_DOMAINS_SYSCALL), %CUR_DOM_ID_BITMAP
|
||||
jz halt
|
||||
|
||||
mov prot_domains_main_esp, %esp
|
||||
|
||||
/* Must be a callee-saved register: */
|
||||
#define ORIG_RET_ADDR edi
|
||||
/* Update the caller's stack to return back to here */
|
||||
pop %ORIG_RET_ADDR
|
||||
push $sysret_dispatcher
|
||||
/* Jump to the system call body */
|
||||
jmp *%SEG_KERN:(%PROT_DOMAINS_SYSCALL)
|
||||
|
||||
sysret_dispatcher:
|
||||
push %ORIG_RET_ADDR
|
||||
|
||||
iret
|
||||
|
||||
/* The task will resume here for the next system call, so it is necessary
|
||||
* to jump back to the top.
|
||||
*/
|
||||
jmp prot_domains_syscall_dispatcher
|
||||
|
||||
.global dev_not_avail_isr
|
||||
dev_not_avail_isr:
|
||||
clts
|
||||
iret
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "gdt.h"
|
||||
#include "helpers.h"
|
||||
#include "idt.h"
|
||||
#include "prot-domains.h"
|
||||
#include "stacks.h"
|
||||
#include "syscalls.h"
|
||||
#include "tss.h"
|
||||
|
||||
uint32_t prot_domains_main_esp;
|
||||
syscalls_entrypoint_t ATTR_KERN_ADDR_SPACE *prot_domains_syscall;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void app_main(void);
|
||||
void
|
||||
prot_domains_reg(dom_client_data_t ATTR_KERN_ADDR_SPACE *dcd,
|
||||
uintptr_t mmio, size_t mmio_sz,
|
||||
uintptr_t meta, size_t meta_sz,
|
||||
bool pio)
|
||||
{
|
||||
segment_desc_t desc;
|
||||
uint32_t eflags;
|
||||
dom_id_t dom_id;
|
||||
volatile struct dom_kern_data ATTR_KERN_ADDR_SPACE *dkd;
|
||||
|
||||
KERN_READL(dom_id, dcd->dom_id);
|
||||
|
||||
dkd = prot_domains_kern_data + dom_id;
|
||||
|
||||
prot_domains_reg_multi_seg(dkd, mmio, mmio_sz, meta, meta_sz);
|
||||
|
||||
/* Only the kernel protection domain requires port I/O access outside of the
|
||||
* interrupt handlers.
|
||||
*/
|
||||
eflags = EFLAGS_IOPL(pio ? PRIV_LVL_USER : PRIV_LVL_INT);
|
||||
if(dom_id == DOM_ID_app) {
|
||||
eflags |= EFLAGS_IF;
|
||||
}
|
||||
|
||||
/* Keep this initialization in sync with the register definitions in
|
||||
* tss-prot-domains-asm.S.
|
||||
*/
|
||||
KERN_WRITEL(dkd->tss.ebp, 0);
|
||||
KERN_WRITEL(dkd->tss.ebx, 0);
|
||||
KERN_WRITEL(dkd->tss.esi, BIT(dom_id));
|
||||
KERN_WRITEL(dkd->tss.eip,
|
||||
(dom_id == DOM_ID_app) ?
|
||||
(uint32_t)app_main :
|
||||
(uint32_t)prot_domains_syscall_dispatcher);
|
||||
KERN_WRITEL(dkd->tss.cs, GDT_SEL_CODE);
|
||||
KERN_WRITEL(dkd->tss.ds, GDT_SEL_DATA);
|
||||
KERN_WRITEL(dkd->tss.es, GDT_SEL_DATA);
|
||||
KERN_WRITEL(dkd->tss.fs, LDT_SEL_KERN);
|
||||
KERN_WRITEL(dkd->tss.gs,
|
||||
(meta_sz == 0) ? GDT_SEL_NULL : LDT_SEL_META);
|
||||
KERN_WRITEL(dkd->tss.ss, GDT_SEL_STK);
|
||||
/* This stack pointer is only actually used in application protection domain.
|
||||
* Other domains enter at system call dispatcher, which switches to main
|
||||
* stack.
|
||||
*/
|
||||
KERN_WRITEL(dkd->tss.esp,
|
||||
/* Two return addresses have been consumed: */
|
||||
STACKS_INIT_TOP + (2 * sizeof(uintptr_t)));
|
||||
KERN_WRITEL(dkd->tss.eflags, eflags);
|
||||
KERN_WRITEL(dkd->tss.ldt, GDT_SEL_LDT(dom_id));
|
||||
KERN_WRITEL(dkd->tss.esp2, STACKS_SIZE_MAIN + STACKS_SIZE_INT);
|
||||
KERN_WRITEL(dkd->tss.ss2, GDT_SEL_STK_INT);
|
||||
KERN_WRITEL(dkd->tss.esp0,
|
||||
STACKS_SIZE_MAIN + STACKS_SIZE_INT + STACKS_SIZE_EXC);
|
||||
KERN_WRITEL(dkd->tss.ss0, GDT_SEL_STK_EXC);
|
||||
KERN_WRITEW(dkd->tss.t, 0);
|
||||
KERN_WRITEW(dkd->tss.iomap_base, sizeof(tss_t));
|
||||
KERN_WRITEL(dkd->tss.cr3, 0);
|
||||
|
||||
segment_desc_init(&desc,
|
||||
KERN_DATA_OFF_TO_PHYS_ADDR((uint32_t)&(dkd->tss)),
|
||||
sizeof(dkd->tss),
|
||||
/* It should be possible for code at any privilege level to invoke the task's
|
||||
* system call dispatcher.
|
||||
*/
|
||||
SEG_FLAG(DPL, PRIV_LVL_USER) | SEG_TYPE_TSS32_AVAIL);
|
||||
|
||||
gdt_insert(GDT_IDX_TSS(dom_id), desc);
|
||||
|
||||
KERN_WRITEW(dcd->tss_sel, GDT_SEL(GDT_IDX_TSS(dom_id), PRIV_LVL_USER));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void dev_not_avail_isr(void);
|
||||
void
|
||||
prot_domains_impl_init(void)
|
||||
{
|
||||
__asm__ __volatile__ ("ltr %0" :: "r" ((uint16_t)GDT_SEL_TSS(DOM_ID_kern)));
|
||||
__asm__ __volatile__ ("lldt %0" :: "r" ((uint16_t)GDT_SEL_LDT(DOM_ID_kern)));
|
||||
|
||||
idt_set_intr_gate_desc(7,
|
||||
(uint32_t)dev_not_avail_isr,
|
||||
GDT_SEL_CODE_EXC, PRIV_LVL_EXC);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int main();
|
||||
void
|
||||
prot_domains_launch_kernel(void)
|
||||
{
|
||||
multi_segment_launch_kernel();
|
||||
|
||||
/* Activate kernel protection domain, entering the kernel at main. */
|
||||
__asm__ __volatile__ (
|
||||
"pushl %[_ss_]\n\t"
|
||||
"pushl %[_top_of_stk_]\n\t"
|
||||
"pushl %[_eflags_]\n\t"
|
||||
"pushl %[_cs_]\n\t"
|
||||
"pushl %[_kern_start_]\n\t"
|
||||
"iretl\n\t"
|
||||
:
|
||||
: [_ss_] "g" (GDT_SEL_STK),
|
||||
[_eflags_] "g" (EFLAGS_IOPL(PRIV_LVL_USER)),
|
||||
[_cs_] "g" (GDT_SEL_CODE),
|
||||
[_kern_start_] "g" (main),
|
||||
/* one address has already been consumed */
|
||||
[_top_of_stk_] "g" (STACKS_INIT_TOP + sizeof(uint32_t))
|
||||
);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
prot_domains_launch_app()
|
||||
{
|
||||
far_pointer_t app_ptr = { 0, GDT_SEL_TSS(DOM_ID_app) };
|
||||
__asm__ __volatile__ ("ljmp *%0" :: "m" (app_ptr));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,130 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_TSS_PROT_DOMAINS_H_
|
||||
#define CPU_X86_MM_TSS_PROT_DOMAINS_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "ldt-layout.h"
|
||||
#include "segmentation.h"
|
||||
#include "tss.h"
|
||||
|
||||
struct dom_kern_data {
|
||||
/** Task State Segment */
|
||||
tss_t tss;
|
||||
/** Local Descriptor Table with per-domain descriptors */
|
||||
segment_desc_t ldt[LDT_NUM_DESC];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* relies on dom_kern_data: */
|
||||
#include "multi-segment.h"
|
||||
|
||||
/* relies on ATTR_KERN_ADDR_SPACE: */
|
||||
#include "syscalls.h"
|
||||
|
||||
/**
|
||||
* Data associated with each protection domain that is owned by clients of that
|
||||
* domain and used to identify the domain.
|
||||
*/
|
||||
struct dom_client_data {
|
||||
dom_id_t dom_id;
|
||||
/** The selector is only 16 bits, but it is padded to 32 bits. */
|
||||
uint32_t tss_sel;
|
||||
};
|
||||
|
||||
extern uint32_t prot_domains_main_esp;
|
||||
|
||||
#define SYSCALLS_STUB_MIDDLE(nm) \
|
||||
/* If already in the callee protection domain, skip the protection */ \
|
||||
/* domain switch and directly invoke the system call body */ \
|
||||
" je _syscall_" #nm "\n\t" \
|
||||
" movl $" EXP_STRINGIFY(_syscall_ent_##nm) ", prot_domains_syscall\n\t" \
|
||||
" mov %esp, prot_domains_main_esp\n\t"
|
||||
|
||||
#define SYSCALLS_STUB(nm) \
|
||||
SYSCALLS_ALLOC_ENTRYPOINT(nm); \
|
||||
asm ( \
|
||||
".text\n\t" \
|
||||
".global " #nm "\n\t" \
|
||||
#nm ":\n\t" \
|
||||
" str %ax\n\t" \
|
||||
/* Compare current Task Register selector to selector for callee */ \
|
||||
/* protection domain, in tss_sel field of dom_client_data */ \
|
||||
" cmpw %ax, 8(%esp)\n\t" \
|
||||
SYSCALLS_STUB_MIDDLE(nm) \
|
||||
/* This will treat the dom_id field as the offset for the call, but */ \
|
||||
/* that is ignored when performing a far call to a task */ \
|
||||
" lcall *4(%esp)\n\t" \
|
||||
" ret\n\t")
|
||||
|
||||
#define SYSCALLS_STUB_SINGLETON(nm, dcd) \
|
||||
SYSCALLS_ALLOC_ENTRYPOINT(nm); \
|
||||
asm ( \
|
||||
".text\n\t" \
|
||||
".global " #nm "\n\t" \
|
||||
#nm ":\n\t" \
|
||||
" str %ax\n\t" \
|
||||
/* Compare current Task Register selector to selector for callee */ \
|
||||
/* protection domain, in tss_sel field of dom_client_data */ \
|
||||
" cmpw %ax, %" SEG_KERN "s:(4 + " #dcd ")\n\t" \
|
||||
SYSCALLS_STUB_MIDDLE(nm) \
|
||||
/* This will treat the dom_id field as the offset for the call, but */ \
|
||||
/* that is ignored when performing a far call to a task */ \
|
||||
" lcall *%" SEG_KERN "s:" #dcd "\n\t" \
|
||||
" ret\n\t")
|
||||
|
||||
#define PROT_DOMAINS_ENTER_ISR(exc) \
|
||||
MULTI_SEGMENT_ENTER_ISR(exc) \
|
||||
/* It is possible that the system call dispatcher is being interrupted, */ \
|
||||
/* and some interrupt handlers perform system calls. Thus, it is */ \
|
||||
/* necessary to save and restore the system call dispatcher parameters */ \
|
||||
/* (in callee-saved registers). */ \
|
||||
"mov prot_domains_main_esp, %%esi\n\t" \
|
||||
"mov prot_domains_syscall, %%edi\n\t" \
|
||||
PROT_DOMAINS_ENTER_ISR_COMMON(exc)
|
||||
#define PROT_DOMAINS_LEAVE_ISR(exc) \
|
||||
PROT_DOMAINS_LEAVE_ISR_COMMON(exc) \
|
||||
"mov %%edi, prot_domains_syscall\n\t" \
|
||||
"mov %%esi, prot_domains_main_esp\n\t" \
|
||||
MULTI_SEGMENT_LEAVE_ISR(exc)
|
||||
|
||||
/* Allocate two additional GDT entries for each protection domain. Note that
|
||||
* the particular storage allocated by this statement may actually be used for
|
||||
* some other protection domain, depending on how the linker happens to arrange
|
||||
* all of the GDT storage. The GDT_IDX_TSS and GDT_IDX_LDT macros in
|
||||
* gdt-layout.h determine which storage is used for each protection domain.
|
||||
* Thus, this storage should not be referenced directly by its variable name.
|
||||
*/
|
||||
#define PROT_DOMAINS_ALLOC_IMPL(nm) \
|
||||
static segment_desc_t ATTR_BSS_GDT_MID _gdt_storage_##nm[2]
|
||||
|
||||
#endif /* CPU_X86_MM_TSS_PROT_DOMAINS_H_ */
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "gdt.h"
|
||||
#include "gdt-layout.h"
|
||||
#include "prot-domains.h"
|
||||
#include "segmentation.h"
|
||||
#include "stacks.h"
|
||||
#include "tss.h"
|
||||
|
||||
/* System-wide TSS */
|
||||
tss_t ATTR_BSS_KERN sys_tss;
|
||||
|
||||
static segment_desc_t ATTR_BSS_GDT sys_tss_desc;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Initialize system-wide TSS.
|
||||
*/
|
||||
void
|
||||
tss_init(void)
|
||||
{
|
||||
segment_desc_t seg_desc;
|
||||
|
||||
/* Initialize TSS */
|
||||
KERN_WRITEW(sys_tss.iomap_base, sizeof(sys_tss));
|
||||
KERN_WRITEL(sys_tss.esp2, ((uint32_t)stacks_int) + STACKS_SIZE_INT);
|
||||
KERN_WRITEL(sys_tss.ss2, GDT_SEL_STK_INT);
|
||||
KERN_WRITEL(sys_tss.esp0, ((uint32_t)stacks_exc) + STACKS_SIZE_EXC);
|
||||
KERN_WRITEL(sys_tss.ss0, GDT_SEL_STK_EXC);
|
||||
|
||||
segment_desc_init(&seg_desc,
|
||||
KERN_DATA_OFF_TO_PHYS_ADDR(&sys_tss), sizeof(sys_tss),
|
||||
SEG_FLAG(DPL, PRIV_LVL_EXC) |
|
||||
SEG_DESCTYPE_SYS | SEG_TYPE_TSS32_AVAIL);
|
||||
gdt_insert(GDT_IDX_OF_DESC(&sys_tss_desc), seg_desc);
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"ltr %0"
|
||||
:
|
||||
: "r" ((uint16_t)GDT_SEL_OF_DESC(&sys_tss_desc, 0)));
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_MM_TSS_H_
|
||||
#define CPU_X86_MM_TSS_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* Task State Segment. Used by the CPU to manage switching between
|
||||
* different protection domains (tasks). The current task is referenced
|
||||
* by the Task Register. When the CPU switches away from a task due to
|
||||
* a far call, etc., it updates the associated in-memory TSS with the
|
||||
* current state of the task. It then loads CPU state from the TSS for
|
||||
* the new task. See Intel Combined Manual, Vol. 3, Chapter 7 for more
|
||||
* details.
|
||||
*/
|
||||
typedef struct tss {
|
||||
uint32_t prev_tsk; /**< The selector of the task that called this one, if applicable */
|
||||
uint32_t esp0; /**< Stack pointer for ring 0 code in this task */
|
||||
uint32_t ss0; /**< Stack segment selector for ring 0 code in this task */
|
||||
uint32_t esp1; /**< Stack pointer for ring 1 code in this task */
|
||||
uint32_t ss1; /**< Stack segment selector for ring 1 code in this task */
|
||||
uint32_t esp2; /**< Stack pointer for ring 2 code in this task */
|
||||
uint32_t ss2; /**< Stack segment selector for ring 2 code in this task */
|
||||
uint32_t cr3; /**< CR3 for this task when paging is enabled */
|
||||
uint32_t eip; /**< Stored instruction pointer value */
|
||||
uint32_t eflags; /**< Settings for EFLAGS register */
|
||||
/** General purpose register values */
|
||||
uint32_t eax, ecx, edx, ebx, esp, ebp, esi, edi;
|
||||
/** Segment register selector values */
|
||||
uint32_t es, cs, ss, ds, fs, gs;
|
||||
/** Selector for Local Descriptor Table */
|
||||
uint32_t ldt;
|
||||
/** Debug-related flag */
|
||||
uint16_t t;
|
||||
/** Offset from base of TSS to base of IO permission bitmap, if one is installed */
|
||||
uint16_t iomap_base;
|
||||
} tss_t;
|
||||
|
||||
void tss_init(void);
|
||||
|
||||
#endif /* CPU_X86_TSS_H_ */
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386")
|
||||
|
||||
ENTRY(start)
|
||||
|
||||
SECTIONS {
|
||||
/*
|
||||
OS-Dev Wiki says it is common for kernels to start at 1M. Addresses before that
|
||||
are used by BIOS/EFI, the bootloader and memory-mapped I/O.
|
||||
|
||||
The UEFI GenFw program inserts a 0x220-byte offset between the image base and
|
||||
the .text section. We add that same offset here to align the symbols in the
|
||||
UEFI DLL with those in the final UEFI binary to make debugging easier. We also
|
||||
apply 32-byte alignments to sections rather than more conventional 4K-byte
|
||||
alignments to avoid symbols being shifted from the intermediate DLL to the
|
||||
final UEFI image as would occur if the GenFw program shifted the .text section
|
||||
from a higher, 4K-aligned offset to the 0x220-byte offset from the image base.
|
||||
Such shifting may make debugging more difficult by preventing the DLL from
|
||||
being a directly-useful source of symbol information. The debugging symbols
|
||||
are not included in the final UEFI image. The GenFw program uses a minimum
|
||||
section alignment of 32 bytes, so smaller alignment granularities may also
|
||||
result in symbol perturbation.
|
||||
*/
|
||||
. = 1M + 0x220;
|
||||
|
||||
.text : ALIGN (32)
|
||||
{
|
||||
KEEP(*(.multiboot))
|
||||
*(.boot_text)
|
||||
*(.text*)
|
||||
}
|
||||
|
||||
/*
|
||||
The alignment directive must be placed after the colon so that the desired
|
||||
alignment is indicated in the ELF section metadata. This metadata is used
|
||||
by the UEFI GenFw program. It is necessary to avoid specifying a smaller
|
||||
alignment value in the ELF metadata for some section "B" that follows some
|
||||
section "A" with an ending address that is not aligned on a 32-byte boundary.
|
||||
In that case, GenFw may place section "B" at a lower starting address in the
|
||||
EFI binary than section "B" had in the input ELF file. This may result in
|
||||
incorrect program behavior. Note that this situation is not directly visible
|
||||
in the EFI binary metadata, since GenFw combines the ELF .rodata, .data, and
|
||||
.bss sections into a single .data section in the EFI binary.
|
||||
*/
|
||||
.rodata : ALIGN (32)
|
||||
{
|
||||
*(.rodata*)
|
||||
|
||||
_sdata_kern_startup_func = .;
|
||||
KEEP(*(.kern_startup_func))
|
||||
_edata_kern_startup_func = .;
|
||||
|
||||
_sdata_shared_isr = .;
|
||||
KEEP(*(.shared_isr_data*))
|
||||
_edata_shared_isr = .;
|
||||
}
|
||||
|
||||
.data : ALIGN (32)
|
||||
{
|
||||
*(.data*)
|
||||
}
|
||||
|
||||
.bss : ALIGN (32)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.main_stack)
|
||||
*(.bss*)
|
||||
|
||||
*(.gdt_bss_start)
|
||||
/*
|
||||
The other GDT-related sections defined in gdt.h are only used when
|
||||
protection domain support is enabled. Thus, they do not need to be
|
||||
included here.
|
||||
*/
|
||||
_ebss_gdt_addr = .;
|
||||
}
|
||||
|
||||
_ebss_pre_dma_addr = ALIGN(32);
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
SECTIONS {
|
||||
|
||||
.bss.dma (NOLOAD) : AT(_ebss_pre_dma_addr) ALIGN (32)
|
||||
{
|
||||
/* IMRs are used to restrict DMA, and they require 1K physical address alignment. */
|
||||
. += ALIGN(_ebss_pre_dma_addr, 1K) - ALIGN(_ebss_pre_dma_addr, 32);
|
||||
*(.dma_bss)
|
||||
}
|
||||
|
||||
_sbss_dma_addr = LOADADDR(.bss.dma) + ALIGN(_ebss_pre_dma_addr, 1K) - ALIGN(_ebss_pre_dma_addr, 32);
|
||||
/*
|
||||
Effectively pointing beyond the end of .bss.dma is acceptable, since
|
||||
.bss.dma is the last section in memory.
|
||||
*/
|
||||
_ebss_dma_addr = ALIGN(LOADADDR(.bss.dma) + SIZEOF(.bss.dma), 1K);
|
||||
|
||||
}
|
|
@ -1,194 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386")
|
||||
|
||||
ENTRY(start)
|
||||
|
||||
/*
|
||||
The TSS-based protection domain implementation does not explicitly reference
|
||||
these symbols, so we list them here to prevent them from being garbage-
|
||||
collected.
|
||||
*/
|
||||
EXTERN(stacks_int)
|
||||
EXTERN(stacks_exc)
|
||||
|
||||
PHDRS {
|
||||
boot_text PT_LOAD;
|
||||
text PT_LOAD;
|
||||
data PT_LOAD;
|
||||
}
|
||||
|
||||
SECTIONS {
|
||||
/*
|
||||
OS-Dev Wiki says it is common for kernels to start at 1M. Addresses before that
|
||||
are used by BIOS/EFI, the bootloader and memory-mapped I/O.
|
||||
|
||||
The UEFI GenFw program inserts a 0x220 byte offset between the image base and
|
||||
the .text section. We add that same offset here to align the symbols in the
|
||||
UEFI DLL with those in the final UEFI binary to make debugging easier.
|
||||
*/
|
||||
. = 1M + 0x220;
|
||||
|
||||
/*
|
||||
The GenFw program in the EDK2 UEFI toolchain outputs UEFI images with a
|
||||
section alignment of at least 32 bytes. Thus, it is desirable to use at
|
||||
least that alignment granularity to avoid symbols being shifted from the
|
||||
intermediate DLL to the final UEFI image. Such shifting may make
|
||||
debugging more difficult by preventing the DLL from being a useful
|
||||
source of symbol information. The debugging symbols are not included in
|
||||
the final UEFI image.
|
||||
*/
|
||||
.text.boot : ALIGN (32)
|
||||
{
|
||||
*(.multiboot)
|
||||
/*
|
||||
The initial bootstrap code expects to operate in a flat address
|
||||
space with an identity mapping between linear and physical
|
||||
addresses.
|
||||
*/
|
||||
*(.boot_text)
|
||||
} :boot_text
|
||||
|
||||
/* The post-boot code segments define tight bounds around the code
|
||||
section, so this directive resets the virtual address to 0. */
|
||||
. = 0;
|
||||
|
||||
/* The virtual address differs from the load address. */
|
||||
.text : AT(LOADADDR(.text.boot) + ALIGN(SIZEOF(.text.boot), 32)) ALIGN (32)
|
||||
{
|
||||
/*
|
||||
These BYTE directives emit a UD2 instruction to cause execution to
|
||||
halt if the control flow ever deviates to address 0. This also
|
||||
prevents other code from being placed at address 0. Some code
|
||||
considers a function pointer to address 0 to be a null function
|
||||
pointer.
|
||||
*/
|
||||
BYTE(0x0F);
|
||||
BYTE(0x0B);
|
||||
*(.text*)
|
||||
|
||||
/*
|
||||
An alternative design to eliminate the need for ALIGN directives
|
||||
within the AT directives in later sections could have padded
|
||||
each section out to a 32-byte boundary. However, that would have
|
||||
enabled unneeded software accesses to the padding past the end of actual
|
||||
code/data in each section, since segments are also configured based on
|
||||
the values of the SIZEOF expressions. As a general principle, accesses
|
||||
should be as restricted as is feasible.
|
||||
*/
|
||||
} :text
|
||||
|
||||
_stext_addr = LOADADDR(.text);
|
||||
_etext_addr = LOADADDR(.text) + SIZEOF(.text);
|
||||
|
||||
. = 0;
|
||||
|
||||
.data : AT(ALIGN(_etext_addr, 32)) ALIGN (32)
|
||||
{
|
||||
*(.main_stack)
|
||||
*(.int_stack)
|
||||
*(.exc_stack)
|
||||
*(.rodata*)
|
||||
*(.data*)
|
||||
|
||||
_sdata_kern_startup_func = .;
|
||||
KEEP(*(.kern_startup_func))
|
||||
_edata_kern_startup_func = .;
|
||||
|
||||
/*
|
||||
These could alternatively be treated as read-only data to prevent tampering
|
||||
from the user privilege level.
|
||||
*/
|
||||
_sdata_shared_isr = .;
|
||||
KEEP(*(.shared_isr_data*))
|
||||
_edata_shared_isr = .;
|
||||
} :data
|
||||
|
||||
.bss : ALIGN (32)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss*)
|
||||
}
|
||||
|
||||
_sdata_addr = LOADADDR(.data);
|
||||
_edata_addr = LOADADDR(.bss) + SIZEOF(.bss);
|
||||
|
||||
. = 0;
|
||||
|
||||
.bss.kern (NOLOAD) : AT(ALIGN(_edata_addr, 32)) ALIGN (32)
|
||||
{
|
||||
/*
|
||||
This directive prevents any data from being allocated at address
|
||||
zero, since the address 0 is commonly used to represent null
|
||||
pointers.
|
||||
*/
|
||||
LONG(0);
|
||||
*(.kern_bss)
|
||||
|
||||
syscalls_entrypoints = .;
|
||||
*(.syscall_bss)
|
||||
syscalls_entrypoints_end = .;
|
||||
}
|
||||
|
||||
_ebss_syscall_addr = LOADADDR(.bss.kern) + SIZEOF(.bss.kern);
|
||||
|
||||
.bss.kern_priv (NOLOAD) : ALIGN (32)
|
||||
{
|
||||
prot_domains_kern_data = .;
|
||||
/*
|
||||
The kernel and app protection domain control structures must always
|
||||
be placed in the first two slots in this order, so that they have
|
||||
well-known protection domain IDs:
|
||||
*/
|
||||
*(.kern_prot_dom_bss)
|
||||
*(.app_prot_dom_bss)
|
||||
*(.prot_dom_bss)
|
||||
prot_domains_kern_data_end = .;
|
||||
|
||||
*(.gdt_bss_start)
|
||||
KEEP(*(.gdt_bss_mid))
|
||||
*(.gdt_bss)
|
||||
_ebss_gdt_addr = .;
|
||||
}
|
||||
|
||||
_sbss_kern_addr = LOADADDR(.bss.kern);
|
||||
_ebss_kern_addr = LOADADDR(.bss.kern_priv) + SIZEOF(.bss.kern_priv);
|
||||
|
||||
. = _ebss_kern_addr;
|
||||
|
||||
.bss.meta (NOLOAD) : AT(ALIGN(_ebss_kern_addr, 32)) ALIGN (32)
|
||||
{
|
||||
*(.meta_bss)
|
||||
}
|
||||
|
||||
/* .bss.meta may be empty, so this uses .bss.kern_priv as a base instead: */
|
||||
_ebss_pre_dma_addr = ALIGN(ALIGN(_ebss_kern_addr, 32) + SIZEOF(.bss.meta), 32);
|
||||
}
|
|
@ -1,210 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-i386")
|
||||
|
||||
ENTRY(start)
|
||||
|
||||
SECTIONS {
|
||||
/*
|
||||
OS-Dev Wiki says it is common for kernels to start at 1M. Addresses before that
|
||||
are used by BIOS/EFI, the bootloader and memory-mapped I/O.
|
||||
|
||||
The UEFI GenFw program inserts a 0x220-byte offset between the image base and
|
||||
the .text section. We add that same offset here to align the symbols in the
|
||||
UEFI DLL with those in the final UEFI binary to make debugging easier.
|
||||
*/
|
||||
. = 1M + 0x220;
|
||||
|
||||
.text.boot : ALIGN (32)
|
||||
{
|
||||
*(.multiboot)
|
||||
*(.boot_text)
|
||||
|
||||
/*
|
||||
Fill out the section to the next 4K boundary so that the UEFI GenFw
|
||||
program does not shift the following .text section forward into the
|
||||
gap and perturb the symbols. This only works if the size of this
|
||||
section is less than 4K - 0x220 bytes.
|
||||
*/
|
||||
. = 4K - 0x220;
|
||||
}
|
||||
|
||||
/*
|
||||
It is actually desired that each of the following sections be page-
|
||||
aligned. However, the UEFI GenFw program ratchets up its alignment
|
||||
granularity to the maximum granularity discovered in its input file.
|
||||
Using page-alignment perturbs the symbols, hindering debugging. Thus,
|
||||
this file simply pads each section out to the desired page alignment and
|
||||
declares a section alignment granularity of 32 bytes.
|
||||
*/
|
||||
|
||||
.text : ALIGN (32)
|
||||
{
|
||||
*(.text*)
|
||||
|
||||
. = ALIGN(4K);
|
||||
}
|
||||
|
||||
_stext_addr = ADDR(.text);
|
||||
_etext_addr = ADDR(.text) + SIZEOF(.text);
|
||||
|
||||
.data.stack : ALIGN (32)
|
||||
{
|
||||
/*
|
||||
Introduce a guard band page before the stacks to facilitate stack
|
||||
overflow detection. This approach wastes a page of memory for each
|
||||
guard band, but has the advantage of enabling an identity mapping
|
||||
for all linear to physical addresses except those in the MMIO
|
||||
regions. The guard bands are marked not-present in the page tables
|
||||
to facilitate stack overflow detection.
|
||||
|
||||
This padding must be placed inside of the section, or else it will
|
||||
get dropped when the UEFI GenFw program generates the UEFI binary.
|
||||
*/
|
||||
. += 4K;
|
||||
|
||||
/*
|
||||
Place the main stack first so that an overflow is detected and does
|
||||
not overwrite the interrupt or supervisor stacks. Usage of the
|
||||
interrupt and stack is predictable, since it is only used by short
|
||||
trampoline code sequences that quickly pivot to the main stack.
|
||||
*/
|
||||
*(.main_stack)
|
||||
*(.int_stack)
|
||||
*(.exc_stack)
|
||||
|
||||
/*
|
||||
The combined sizes of the stacks is an even multiple of 4K, so there
|
||||
is no need to align the location counter here.
|
||||
*/
|
||||
|
||||
/*
|
||||
Introduce a guard band page after the stacks to detect stack underflow.
|
||||
Note that an underflow that only affects the interrupt and supervisor
|
||||
stacks will not generate a page fault. Detecting such conditions by
|
||||
placing the interrupt and supervisor stacks on separate pages would
|
||||
substantially increase memory usage.
|
||||
*/
|
||||
. += 4K;
|
||||
}
|
||||
|
||||
.data : ALIGN (32)
|
||||
{
|
||||
/*
|
||||
The UEFI GenFw program treats all sections that are alloc and read-
|
||||
only as code sections. By that criteria, .rodata would be a code
|
||||
section, but making such data executable is undesirable. Thus, this
|
||||
script lumps in .rodata with other data. It may be desirable in the
|
||||
future to actually write-protect this data.
|
||||
*/
|
||||
*(.rodata*)
|
||||
*(.data*)
|
||||
|
||||
_sdata_kern_startup_func = .;
|
||||
KEEP(*(.kern_startup_func))
|
||||
_edata_kern_startup_func = .;
|
||||
|
||||
/*
|
||||
These could alternatively be treated as read-only data to prevent tampering
|
||||
from the user privilege level.
|
||||
*/
|
||||
_sdata_shared_isr = .;
|
||||
KEEP(*(.shared_isr_data*))
|
||||
_edata_shared_isr = .;
|
||||
|
||||
. = ALIGN(4K);
|
||||
}
|
||||
|
||||
.bss : ALIGN (32)
|
||||
{
|
||||
*(COMMON)
|
||||
*(.bss*)
|
||||
|
||||
. = ALIGN(4K);
|
||||
}
|
||||
|
||||
_sdata_addr = ADDR(.data);
|
||||
_edata_addr = ADDR(.bss) + SIZEOF(.bss);
|
||||
|
||||
.bss.kern (NOLOAD) : ALIGN (32)
|
||||
{
|
||||
/*
|
||||
Page-aligned data is output first.
|
||||
It is infeasible to apply a page-alignment attribute to them in the
|
||||
source code, because that increases the alignment of this section to
|
||||
be page-aligned, which causes problems when generating a UEFI binary
|
||||
as described above.
|
||||
*/
|
||||
*(.page_aligned_kern_bss)
|
||||
*(.kern_bss)
|
||||
|
||||
syscalls_entrypoints = .;
|
||||
*(.syscall_bss)
|
||||
syscalls_entrypoints_end = .;
|
||||
|
||||
. = ALIGN(4K);
|
||||
}
|
||||
|
||||
_ebss_syscall_addr = ADDR(.bss.kern) + SIZEOF(.bss.kern);
|
||||
|
||||
.bss.kern_priv (NOLOAD) : ALIGN (32)
|
||||
{
|
||||
prot_domains_kern_data = .;
|
||||
/*
|
||||
The kernel and app protection domain control structures must always
|
||||
be placed in the first two slots in this order, so that they have
|
||||
well-known protection domain IDs:
|
||||
*/
|
||||
*(.kern_prot_dom_bss)
|
||||
*(.app_prot_dom_bss)
|
||||
*(.prot_dom_bss)
|
||||
prot_domains_kern_data_end = .;
|
||||
|
||||
*(.gdt_bss_start)
|
||||
*(.gdt_bss_mid)
|
||||
*(.gdt_bss)
|
||||
_ebss_gdt_addr = .;
|
||||
|
||||
. = ALIGN(4K);
|
||||
}
|
||||
|
||||
_sbss_kern_addr = ADDR(.bss.kern);
|
||||
_ebss_kern_addr = ADDR(.bss.kern_priv) + SIZEOF(.bss.kern_priv);
|
||||
|
||||
.bss.meta (NOLOAD) : ALIGN (32)
|
||||
{
|
||||
*(.meta_bss)
|
||||
|
||||
. = ALIGN(4K);
|
||||
}
|
||||
|
||||
_ebss_pre_dma_addr = ALIGN(32);
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_STARTUP_H_
|
||||
#define CPU_X86_STARTUP_H_
|
||||
|
||||
/**
|
||||
* \brief Declare a function that will be automatically invoked from the kernel
|
||||
* protection domain during boot, after all of the default device
|
||||
* initialization has been completed.
|
||||
*/
|
||||
#define KERN_STARTUP_FUNC(f) \
|
||||
static void f(void); \
|
||||
static uintptr_t \
|
||||
__attribute__((used, section(".kern_startup_func"))) \
|
||||
__kern_startup_f = (uintptr_t)f; \
|
||||
static void f(void)
|
||||
|
||||
#endif /* CPU_X86_STARTUP_H_ */
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
|
||||
#define MAX_MEM_DESC 128
|
||||
|
||||
void start(void);
|
||||
|
||||
/* The section attribute below is copied from ATTR_BOOT_CODE in prot-domains.h.
|
||||
* prot-domains.h includes stdlib.h which defines NULL. The UEFI headers also
|
||||
* define NULL, which induces a warning when the compiler detects the conflict.
|
||||
* To avoid that, we avoid including prot-domains.h from this file.
|
||||
*/
|
||||
EFI_STATUS EFIAPI __attribute__((section(".boot_text")))
|
||||
uefi_start(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
|
||||
{
|
||||
EFI_MEMORY_DESCRIPTOR mem_map[MAX_MEM_DESC];
|
||||
UINTN mem_map_len = sizeof(mem_map);
|
||||
UINTN mem_map_key;
|
||||
UINTN mem_map_desc_sz;
|
||||
UINT32 mem_map_rev;
|
||||
|
||||
EFI_STATUS res;
|
||||
|
||||
res = SystemTable->BootServices->GetMemoryMap(&mem_map_len,
|
||||
mem_map,
|
||||
&mem_map_key,
|
||||
&mem_map_desc_sz,
|
||||
&mem_map_rev);
|
||||
if(res != EFI_SUCCESS) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
res = SystemTable->BootServices->ExitBootServices(ImageHandle, mem_map_key);
|
||||
if(res != EFI_SUCCESS) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
start();
|
||||
|
||||
/* Should not be reachable: */
|
||||
return EFI_SUCCESS;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
|
||||
# This script will always run on its own basepath, no matter where you call it from.
|
||||
pushd ${SCRIPT_DIR}
|
||||
|
||||
if [ "$(uname -m)" = "x86_64" ]; then
|
||||
export ARCH=X64
|
||||
fi
|
||||
|
||||
# Download the UEFI tool and library sources:
|
||||
if [ -e edk2 ]; then
|
||||
make -C edk2/BaseTools/Source/C/Common clean
|
||||
make -C edk2/BaseTools/Source/C/GenFw clean
|
||||
else
|
||||
git clone --depth=1 https://github.com/tianocore/edk2 || exit
|
||||
fi
|
||||
# Build common sources required by the GenFw tool:
|
||||
make -C edk2/BaseTools/Source/C/Common || exit
|
||||
# Build the GenFw tool that is used to generate UEFI binaries:
|
||||
make -C edk2/BaseTools/Source/C/GenFw || exit
|
||||
# Create a makefile that indicates to the Contiki build system that UEFI support
|
||||
# should be built:
|
||||
echo "EN_UEFI = 1" > Makefile.uefi
|
||||
|
||||
popd
|
|
@ -1,59 +0,0 @@
|
|||
GDB ?= gdb
|
||||
OPENOCD_SCRIPTS = $(CONTIKI)/arch/platform/galileo/bsp/openocd-scripts
|
||||
|
||||
.PHONY: debug $(CONTIKI_PROJECT)
|
||||
|
||||
# Multiboot ELF binary
|
||||
MULTIBOOT_SFX = $(TARGET)
|
||||
MULTIBOOT = $(CONTIKI_PROJECT).$(MULTIBOOT_SFX)
|
||||
# UEFI binary
|
||||
UEFI_DLL_SFX = $(TARGET).dll
|
||||
UEFI_DLL = $(CONTIKI_PROJECT).$(UEFI_SFX)
|
||||
# The GenFw program is unable to process absolute symbols like _stext_addr,
|
||||
# etc., that are defined in quarkX1000_dma.ld and quarkX1000_multi_seg.ld
|
||||
# and used to configure segments in multi-segment.c, etc. Furthermore,
|
||||
# relocating the UEFI image during load would result in those symbols not
|
||||
# pointing to the expected image locations. So, relocation data is omitted
|
||||
# from the intermediate UEFI DLL. This will only result in a
|
||||
# correctly-functioning build if the UEFI firmware does not attempt to
|
||||
# relocate the UEFI image, so it may be desirable in the future to revisit
|
||||
# this design. To emit relocation data, '-Xlinker --emit-relocs' should be
|
||||
# appended to the following line.
|
||||
UEFI_LDFLAGS = -Xlinker --entry=uefi_start
|
||||
UEFI_SFX = $(TARGET).efi
|
||||
UEFI = $(CONTIKI_PROJECT).$(UEFI_SFX)
|
||||
|
||||
# Suffixes for final (non-intermediate) files to be built
|
||||
FINAL_SFXS = $(MULTIBOOT_SFX)
|
||||
ifeq ($(EN_UEFI),1)
|
||||
FINAL_SFXS += $(UEFI_SFX)
|
||||
endif
|
||||
|
||||
debug: $(MULTIBOOT)
|
||||
@openocd -s $(OPENOCD_SCRIPTS) -f debug.cfg &> $(shell pwd)/LOG_OPENOCD &
|
||||
@$(GDB) $< -ex "target remote :3333"
|
||||
|
||||
CUSTOM_RULE_LINK=1
|
||||
|
||||
%.$(MULTIBOOT_SFX): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a
|
||||
$(TRACE_LD)
|
||||
$(Q)$(LD) $(LDFLAGS) $(MULTIBOOT_LDFLAGS) $(TARGET_STARTFILES) ${filter-out %.a,$^} \
|
||||
${filter %.a,$^} $(TARGET_LIBFILES) -o $@
|
||||
|
||||
%.$(UEFI_DLL_SFX): %.co $(PROJECT_OBJECTFILES) $(PROJECT_LIBRARIES) contiki-$(TARGET).a
|
||||
$(TRACE_LD)
|
||||
$(Q)$(LD) $(LDFLAGS) $(UEFI_LDFLAGS) $(TARGET_STARTFILES) ${filter-out %.a,$^} \
|
||||
${filter %.a,$^} $(TARGET_LIBFILES) -o $@
|
||||
|
||||
%.$(UEFI_SFX): %.$(UEFI_DLL_SFX)
|
||||
$(Q)$(GEN_FW) -o $@ -e UEFI_APPLICATION $^
|
||||
# The Intel Galileo firmware has been observed to not relocate the image
|
||||
# if its base is set to the 1M boundary. This makes debugging easier,
|
||||
# since the symbols in the intermediate DLL then correspond to the load
|
||||
# addresses.
|
||||
$(Q)$(GEN_FW) -o $@ --rebase 0x100000 $@
|
||||
|
||||
$(CONTIKI_PROJECT): $(addprefix $(CONTIKI_PROJECT).,$(FINAL_SFXS))
|
||||
@$(SIZE) $^
|
||||
|
||||
CLEAN += $(addprefix $(CONTIKI_PROJECT).,$(FINAL_SFXS))
|
|
@ -1,43 +0,0 @@
|
|||
BSP_PATH=$(CONTIKI)/arch/platform/galileo/bsp
|
||||
LIBC_PATH=$(BSP_PATH)/libc
|
||||
LIBC=$(LIBC_PATH)/i586-elf
|
||||
LIBGCC_PATH = /usr/lib/gcc/$(shell gcc -dumpmachine)/$(shell gcc -dumpversion)
|
||||
|
||||
CONTIKI_TARGET_DIRS = . core/sys/ drivers/ net/
|
||||
CONTIKI_TARGET_MAIN = ${addprefix $(OBJECTDIR)/,contiki-main.o}
|
||||
CONTIKI_SOURCEFILES += contiki-main.c clock.c rtimer-arch.c eth-proc.c eth-conf.c galileo-gpio.c
|
||||
|
||||
GALILEO_GEN ?= 2
|
||||
CFLAGS += -DGALILEO_GEN=$(GALILEO_GEN)
|
||||
CONTIKI_SOURCEFILES += galileo-gen$(GALILEO_GEN)-pinmux.c
|
||||
|
||||
ifeq ($(GALILEO_GEN),2)
|
||||
CONTIKI_SOURCEFILES += gpio-pcal9535a.c pwm-pca9685.c
|
||||
else
|
||||
CONTIKI_SOURCEFILES += cy8c9540a.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONTIKI_WITH_IPV6),1)
|
||||
CONTIKI_SOURCEFILES += nbr-table.c packetbuf.c linkaddr.c link-stats.c
|
||||
endif
|
||||
|
||||
PROJECT_SOURCEFILES += newlib-syscalls.c
|
||||
|
||||
CONTIKI_CPU=$(CONTIKI)/arch/cpu/x86
|
||||
include $(CONTIKI)/arch/cpu/x86/Makefile.x86_quarkX1000
|
||||
|
||||
CFLAGS += -fno-stack-protector -I$(LIBC)/include
|
||||
ifeq (clang,$(findstring clang,$(CC)))
|
||||
CFLAGS += -nostdlibinc
|
||||
else
|
||||
CFLAGS += -nostdinc -isystem $(LIBGCC_PATH)/include -isystem $(LIBGCC_PATH)/include-fixed
|
||||
endif
|
||||
LDFLAGS += -nostdlib -L$(LIBC)/lib -L$(LIBGCC_PATH)/32
|
||||
|
||||
TARGET_LIBFILES += -lm -lc -lgcc
|
||||
|
||||
-include $(LIBC_PATH)/Makefile.libc
|
||||
|
||||
ifndef BUILT_LIBC
|
||||
$(error Build the C library by executing $(LIBC_PATH)/build_newlib.sh)
|
||||
endif
|
|
@ -1,285 +0,0 @@
|
|||
Intel Galileo Board
|
||||
===================
|
||||
|
||||
This README file contains general information about the Intel Galileo board
|
||||
support. In the following lines you will find information about supported
|
||||
features as well as instructions on how to build, run and debug applications
|
||||
for this platform. The instructions were only test in Linux environment.
|
||||
|
||||
Requirements
|
||||
------------
|
||||
|
||||
In order to build and debug the following packages must be installed in your
|
||||
system:
|
||||
* gcc
|
||||
* gdb
|
||||
* openocd
|
||||
|
||||
Moreover, in order to debug via JTAG or serial console, you will some extra
|
||||
devices as described in [1] and [2].
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
This section presents the features currently supported (e.g. device drivers
|
||||
and Contiki APIs) by the Galileo port.
|
||||
|
||||
Device drivers:
|
||||
* Programmable Interrupt Controller (PIC)
|
||||
* Programmable Intergal Timer (PIT)
|
||||
* Real-Time Clock (RTC)
|
||||
* UART
|
||||
* Ethernet
|
||||
* I2C
|
||||
* GPIO (default pinmux configuration is listed in
|
||||
platform/galileo/drivers/galileo-pinmux.c)
|
||||
* Intel Quark X1000 SoC message bus
|
||||
* Isolated Memory Regions (IMRs)
|
||||
|
||||
Contiki APIs:
|
||||
* Clock module
|
||||
* Timer, Stimer, Etimer, Ctimer, and Rtimer libraries
|
||||
|
||||
Standard APIs:
|
||||
* Stdio library (stdout and stderr only). Console output through UART 1
|
||||
device (connected to Galileo Gen2 FTDI header)
|
||||
|
||||
Optional support for protection domains is also implemented and is
|
||||
described in cpu/x86/mm/README.md.
|
||||
|
||||
Preparation
|
||||
-----------
|
||||
|
||||
Prerequisites on all Ubuntu Linux systems include texinfo and uuid-dev.
|
||||
Additional prerequisites on 64-bit Ubuntu Linux systems include
|
||||
gcc-multilib and g++-multilib.
|
||||
|
||||
Docker can optionally be used to prepare an Ubuntu-based, containerized build
|
||||
environment. This has been tested with Docker installed on Microsoft Windows 10.
|
||||
|
||||
If not using a containerized environment, proceed to the "Building" section
|
||||
below.
|
||||
|
||||
Using a Docker-based environment on Windows requires that the repository has
|
||||
been checked out with Git configured to preserve UNIX-style line endings. This
|
||||
can be accomplished by changing the 'core.autocrlf' setting prior to cloning
|
||||
the repository [5]:
|
||||
```
|
||||
git config --global core.autocrlf input
|
||||
```
|
||||
Note that this is a global setting, so it may affect other Git operations.
|
||||
|
||||
The drive containing the repository needs to be shared with Docker containers
|
||||
for the following steps to work [6]. Note that this is a global setting that
|
||||
affects other containers that may be present on the host.
|
||||
|
||||
Open Microsoft PowerShell and navigate to the base directory of the repository.
|
||||
Run the following command to create the build environment:
|
||||
```
|
||||
docker build -t contiki-galileo-build platform/galileo/bsp/docker
|
||||
```
|
||||
This creates a container named 'contiki-galileo-build' based on Ubuntu and
|
||||
installs development tools in the container.
|
||||
|
||||
The build commands shown below can be run within the newly-created container. To
|
||||
obtain a shell, run the following command in PowerShell from the base directory
|
||||
of the repository.
|
||||
```
|
||||
docker run -t -i -v ${Pwd}:/contiki contiki-galileo-build
|
||||
```
|
||||
This command mounts the current directory and its subdirectories at the path
|
||||
'/contiki' within the container. Changes to those files in the container are
|
||||
visible to the host and vice versa. However, changes to the container
|
||||
filesystem are not automatically persisted when the container is stopped.
|
||||
|
||||
The containerized build environment does not currently support building the Grub
|
||||
bootloader nor debugging using the instructions in this document.
|
||||
|
||||
See the Docker Overview for more information about working with containers [7].
|
||||
|
||||
Building
|
||||
--------
|
||||
|
||||
To build applications for this platform you should first build newlib (in
|
||||
case it wasn't already built). To build newlib you can run the following
|
||||
command:
|
||||
```
|
||||
$ ./platform/galileo/bsp/libc/build_newlib.sh
|
||||
```
|
||||
|
||||
Once newlib is built, you are ready to build applications. By default, the
|
||||
following steps will use gcc as the C compiler and to invoke the linker. To
|
||||
use LLVM clang instead, change the values for both the CC and LD variables in
|
||||
cpu/x86/Makefile.x86_common to 'clang'.
|
||||
|
||||
To build applications for the Galileo platform you should set the TARGET
|
||||
variable to 'galileo'. For instance, building the hello-world application
|
||||
should look like this:
|
||||
```
|
||||
$ cd examples/hello-world/ && make TARGET=galileo
|
||||
```
|
||||
|
||||
This will generate the 'hello-world.galileo' file which is a multiboot-
|
||||
compliant [3] ELF image. This image contains debugging information and it
|
||||
should be used in your daily development.
|
||||
|
||||
You can also build a "Release" image by setting the BUILD_RELEASE variable to
|
||||
1. This will generate a Contiki stripped-image optimized for size.
|
||||
```
|
||||
$ cd examples/hello-world/ && make TARGET=galileo BUILD_RELEASE=1
|
||||
```
|
||||
|
||||
To also generate an '<application>.galileo.efi' file which is a UEFI [4] image,
|
||||
you can run the following command prior to building applications:
|
||||
```
|
||||
$ cpu/x86/uefi/build_uefi.sh
|
||||
```
|
||||
|
||||
To restrict DMA so that peripherals are blocked from accessing memory
|
||||
regions that do not contain any data that needs to be DMA-accessible,
|
||||
specify X86_CONF_RESTRICT_DMA=1 as a command-line argument to the make
|
||||
command that is used to build the image. This will configure and lock
|
||||
the IMRs.
|
||||
|
||||
Galileo Gen. 2 is targeted by default. Specify GALILEO_GEN=1 on the build
|
||||
command line to target first generation boards.
|
||||
|
||||
Running
|
||||
-------
|
||||
|
||||
You will need a multiboot-compliant bootloader to boot Contiki images in that
|
||||
format. However, this is not needed for booting UEFI images.
|
||||
|
||||
In the bsp directory, we provide a helper script which builds the Grub
|
||||
bootloader with multiboot support. To build the bootloader, just run the
|
||||
following command:
|
||||
```
|
||||
$ platform/galileo/bsp/grub/build_grub.sh
|
||||
```
|
||||
|
||||
Once Grub is built, we have three main steps to run Contiki applications:
|
||||
prepare SDcard, connect to console, and boot image. Below follows
|
||||
detailed instructions.
|
||||
|
||||
### Prepare SDcard
|
||||
|
||||
The instructions in this section are for a native Linux development environment,
|
||||
so equivalent operations should be substituted when using some other environment
|
||||
(e.g. Windows Explorer can be used to perform equivalent operations when using
|
||||
Docker on Windows as a development environment).
|
||||
|
||||
Mount the sdcard in directory /mnt/sdcard.
|
||||
|
||||
Create UEFI boot directory:
|
||||
```
|
||||
$ mkdir -p /mnt/sdcard/efi/boot
|
||||
```
|
||||
|
||||
#### Approach for Multiboot-compliant ELF Image
|
||||
|
||||
Copy Contiki binary image to sdcard
|
||||
```
|
||||
$ cp examples/hello-world/hello-world.galileo /mnt/sdcard
|
||||
```
|
||||
|
||||
Copy grub binary to sdcard
|
||||
```
|
||||
$ cp platform/galileo/bsp/grub/bin/grub.efi /mnt/sdcard/efi/boot/bootia32.efi
|
||||
```
|
||||
|
||||
#### Approach for UEFI Image
|
||||
|
||||
Copy Contiki binary image to sdcard:
|
||||
```
|
||||
$ cp examples/hello-world/hello-world.galileo.efi /mnt/sdcard/efi/boot/bootia32.efi
|
||||
```
|
||||
|
||||
### Connect to the console output
|
||||
|
||||
Connect the serial cable to your computer as shown in [8] for first generation
|
||||
boards and [2] for second generation boards.
|
||||
|
||||
Choose a terminal emulator such as PuTTY. Make sure you use the SCO keyboard
|
||||
mode (on PuTTY that option is at Terminal -> Keyboard, on the left menu).
|
||||
Connect to the appropriate serial port using a baud rate of 115200.
|
||||
|
||||
### Boot Contiki Image
|
||||
|
||||
Turn on your board. After a few seconds you should see the following text
|
||||
in the screen:
|
||||
```
|
||||
Press [Enter] to directly boot.
|
||||
Press [F7] to show boot menu options.
|
||||
```
|
||||
|
||||
Waiting for the system to select the default boot device may be sufficient.
|
||||
However, if this does not boot Contiki or Grub (depending on what is installed
|
||||
as the UEFI boot image) then perform the following procedure after rebooting
|
||||
and waiting for the boot message to appear: Press <F7> and select the option
|
||||
"UEFI Misc Device" within the menu.
|
||||
|
||||
No additional steps should be required to boot a Contiki UEFI image.
|
||||
|
||||
Run the following additional commands to boot a multiboot-compliant image:
|
||||
```
|
||||
$ multiboot /hello-world.galileo
|
||||
$ boot
|
||||
```
|
||||
|
||||
### Verify that Contiki is Running
|
||||
|
||||
This should boot the Contiki image, resulting in the following messages being
|
||||
sent to the serial console:
|
||||
```
|
||||
Starting Contiki
|
||||
Hello, world
|
||||
```
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
This section describes how to debug Contiki via JTAG. The following
|
||||
instructions consider you have the devices: Flyswatter2 and ARM-JTAG-20-10
|
||||
adapter (see [1]).
|
||||
|
||||
Attach the Flyswatter2 to your host computer with an USB cable. Connect the
|
||||
Flyswatter2 and ARM-JTAG-20-10 adapter using the 20-pins head. Connect the
|
||||
ARM-JTAG-20-10 adapter to Galileo Gen2 JTAG port using the 10-pins head.
|
||||
|
||||
Once everything is connected, run Contiki as described in "Running" section,
|
||||
but right after loading Contiki image (multiboot command), run the following
|
||||
command:
|
||||
```
|
||||
$ make TARGET=galileo debug
|
||||
```
|
||||
|
||||
The 'debug' rule will run OpenOCD and gdb with the right parameters. OpenOCD
|
||||
will run in background and its output will be redirected to a log file in the
|
||||
application's path called LOG_OPENOCD. Once gdb client is detached, OpenOCD
|
||||
is terminated.
|
||||
|
||||
If you use a gdb front-end, you can define the "GDB" environment
|
||||
variable and your gdb front-end will be used instead of default gdb.
|
||||
For instance, if you want to use cgdb front-end, just run the command:
|
||||
```
|
||||
$ make BOARD=galileo debug GDB=cgdb
|
||||
```
|
||||
|
||||
References
|
||||
----------
|
||||
|
||||
[1] https://communities.intel.com/message/211778
|
||||
|
||||
[2] https://software.intel.com/en-us/articles/intel-galileo-gen-2-board-assembly-using-eclipse-and-intel-xdk-iot-edition
|
||||
|
||||
[3] https://www.gnu.org/software/grub/manual/multiboot/multiboot.html
|
||||
|
||||
[4] http://www.uefi.org/
|
||||
|
||||
[5] https://www.git-scm.com/book/en/v2/Customizing-Git-Git-Configuration
|
||||
|
||||
[6] https://docs.docker.com/docker-for-windows/#/shared-drives
|
||||
|
||||
[7] https://docs.docker.com/engine/understanding-docker/
|
||||
|
||||
[8] https://software.intel.com/en-us/articles/intel-galileo-gen-1-board-assembly-using-eclipse-and-intel-xdk-iot-edition
|
|
@ -1,8 +0,0 @@
|
|||
FROM ubuntu:16.04
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y \
|
||||
gcc-multilib g++-multilib git make patch texinfo uuid-dev wget \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
WORKDIR /contiki
|
||||
ENV TARGET galileo
|
||||
CMD ["/bin/bash", "-l"]
|
|
@ -1,60 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
JOBS=5
|
||||
HEAD="bac5d1a64ab4191058a8fd4c05f6b3b339e249e7"
|
||||
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
|
||||
prepare() {
|
||||
if [[ ! -d ./src ]]; then
|
||||
git clone git://git.savannah.gnu.org/grub.git src
|
||||
fi
|
||||
|
||||
pushd src
|
||||
git checkout $HEAD
|
||||
git clean -fdx
|
||||
popd
|
||||
}
|
||||
|
||||
build() {
|
||||
pushd src
|
||||
|
||||
./autogen.sh
|
||||
./configure --with-platform=efi --target=i386
|
||||
|
||||
make -j${JOBS}
|
||||
|
||||
./grub-mkimage -p /EFI/BOOT -d ./grub-core/ -O i386-efi -o grub.efi \
|
||||
boot efifwsetup efi_gop efinet efi_uga lsefimmap lsefi lsefisystab \
|
||||
exfat fat multiboot2 multiboot terminal part_msdos part_gpt normal \
|
||||
all_video aout configfile echo file fixvideo fshelp gfxterm gfxmenu \
|
||||
gfxterm_background gfxterm_menu legacycfg video_bochs video_cirrus \
|
||||
video_colors video_fb videoinfo video
|
||||
|
||||
popd
|
||||
}
|
||||
|
||||
setup() {
|
||||
mkdir -p bin
|
||||
cp src/grub.efi bin/
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
rm -rf ./src
|
||||
rm -rf ./bin
|
||||
}
|
||||
|
||||
# This script will always run on its own basepath, no matter where you call it from.
|
||||
pushd ${SCRIPT_DIR}
|
||||
|
||||
case $1 in
|
||||
-c | --cleanup)
|
||||
cleanup
|
||||
;;
|
||||
*)
|
||||
prepare && build && setup
|
||||
;;
|
||||
esac
|
||||
|
||||
popd
|
|
@ -1,119 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
JOBS=5
|
||||
TARGET=i586-elf
|
||||
VERSION=2.2.0-1
|
||||
MD5=94114fdc1d8391cdbc2653d89249cccf
|
||||
PKG_NAME=newlib
|
||||
SRC_DIR=${PKG_NAME}-${VERSION}
|
||||
PATCH_DIR=../patches
|
||||
TARBALL=${SRC_DIR}.tar.gz
|
||||
DIST_SITE=ftp://sources.redhat.com/pub/newlib
|
||||
|
||||
SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
|
||||
|
||||
# This script will always run on its own basepath, no matter where you call it from.
|
||||
pushd ${SCRIPT_DIR}
|
||||
|
||||
prepare() {
|
||||
# If the source tarball doesn't exist of its md5 checksum doesn't match, download it.
|
||||
if [ ! -e ./${TARBALL} ] || [ "$(md5sum ./${TARBALL} | cut -d' ' -f1)" != $MD5 ]; then
|
||||
wget -c ${DIST_SITE}/${TARBALL}
|
||||
fi
|
||||
if [ ! -e ./${TARBALL} ] || [ "$(md5sum ./${TARBALL} | cut -d' ' -f1)" != $MD5 ]; then
|
||||
echo "Error obtaining tarball."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Clean up the previous source dir, if any.
|
||||
if [[ -d ./${SRC_DIR} ]]; then
|
||||
rm -rf ./${SRC_DIR}
|
||||
fi
|
||||
|
||||
# Clean up the previous install dir, if any.
|
||||
if [[ -d ./${TARGET} ]]; then
|
||||
rm -rf ./${TARGET}
|
||||
fi
|
||||
|
||||
tar xf ${TARBALL}
|
||||
cd ${SRC_DIR}
|
||||
|
||||
for i in `ls ${PATCH_DIR}/*.patch`; do patch -p0 < ${i}; done
|
||||
}
|
||||
|
||||
|
||||
build() {
|
||||
export AR_FOR_TARGET=ar
|
||||
export AS_FOR_TARGET=as
|
||||
export CC_FOR_TARGET=cc
|
||||
export GCC_FOR_TARGET=gcc
|
||||
export CXX_FOR_TARGET=c++
|
||||
export RAW_CXX_FOR_TARGET=c++
|
||||
export GCJ_FOR_TARGET=gcj
|
||||
export GFORTRAN_FOR_TARGET=gfortran
|
||||
export GOC_FOR_TARGET=gccgo
|
||||
export DLLTOOL_FOR_TARGET=dlltool
|
||||
export LD_FOR_TARGET=ld
|
||||
export LIPO_FOR_TARGET=lipo
|
||||
export NM_FOR_TARGET=nm
|
||||
export OBJDUMP_FOR_TARGET=objdump
|
||||
export RANLIB_FOR_TARGET=ranlib
|
||||
export READELF_FOR_TARGET=readelf
|
||||
export STRIP_FOR_TARGET=strip
|
||||
export WINDRES_FOR_TARGET=windres
|
||||
export WINDMC_FOR_TARGET=windmc
|
||||
export COMPILER_AS_FOR_TARGET=as
|
||||
export COMPILER_LD_FOR_TARGET=ld
|
||||
export COMPILER_NM_FOR_TARGET=nm
|
||||
export CFLAGS_FOR_TARGET="-Os -m32 -march=i586 -mtune=i586 -fno-stack-protector -DPREFER_SIZE_OVER_SPEED -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-unwind-tables"
|
||||
export CXXFLAGS_FOR_TARGET="-Os -m32 -march=i586 -mtune=i586 -fno-stack-protector -DPREFER_SIZE_OVER_SPEED -ffunction-sections -fdata-sections -fno-asynchronous-unwind-tables -fno-unwind-tables"
|
||||
|
||||
mkdir -p install
|
||||
./configure --target=${TARGET} \
|
||||
--prefix=`pwd`/install \
|
||||
--enable-newlib-nano-formatted-io \
|
||||
--enable-newlib-nano-malloc \
|
||||
--enable-multithread \
|
||||
--disable-newlib-fvwrite-in-streamio \
|
||||
--disable-newlib-fseek-optimization \
|
||||
--disable-newlib-wide-orient \
|
||||
--disable-newlib-unbuf-stream-opt \
|
||||
--disable-libstdcxx \
|
||||
--disable-multilib \
|
||||
--disable-newlib-mb \
|
||||
--disable-newlib-supplied-syscalls
|
||||
|
||||
make -j${JOBS} all && make install
|
||||
cd ..
|
||||
|
||||
echo "BUILT_LIBC = newlib" > Makefile.libc
|
||||
}
|
||||
|
||||
setup() {
|
||||
cp -r ./${SRC_DIR}/install/${TARGET} .
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
rm -rf ./${SRC_DIR}*
|
||||
}
|
||||
|
||||
|
||||
# By default we always call prepare, build and setup.
|
||||
prepare
|
||||
build
|
||||
setup
|
||||
|
||||
# But we only cleanup if -c is used.
|
||||
case $1 in
|
||||
-c | --cleanup)
|
||||
cleanup
|
||||
shift
|
||||
;;
|
||||
*)
|
||||
# unknown option
|
||||
;;
|
||||
esac
|
||||
|
||||
popd
|
|
@ -1,11 +0,0 @@
|
|||
--- newlib/libc/include/sys/config.h 2015-01-14 07:25:15.000000000 -0200
|
||||
+++ newlib/libc/include/sys/config.h 2015-03-13 14:21:33.247980336 -0300
|
||||
@@ -94,9 +94,6 @@
|
||||
#define HAVE_GETDATE
|
||||
#define _HAVE_SYSTYPES
|
||||
#define _READ_WRITE_RETURN_TYPE _ssize_t
|
||||
-#define __LARGE64_FILES 1
|
||||
-/* we use some glibc header files so turn on glibc large file feature */
|
||||
-#define _LARGEFILE64_SOURCE 1
|
||||
#endif
|
||||
#endif
|
|
@ -1,13 +0,0 @@
|
|||
--- newlib/configure.host 2015-03-12 17:59:39.380318464 -0300
|
||||
+++ newlib/configure.host 2015-03-12 17:55:05.933645678 -0300
|
||||
@@ -810,6 +810,10 @@
|
||||
z8k-*-*)
|
||||
syscall_dir=syscalls
|
||||
;;
|
||||
+ i586-*-elf)
|
||||
+ newlib_cflags="${newlib_cflags} -DREENTRANT_SYSCALLS_PROVIDED"
|
||||
+ syscall_dir=syscalls
|
||||
+ ;;
|
||||
*)
|
||||
newlib_cflags="${newlib_cflags} -DMISSING_SYSCALL_NAMES"
|
||||
syscall_dir=
|
|
@ -1,19 +0,0 @@
|
|||
--- newlib/libc/stdio/nano-vfprintf_local.h 2014-07-04 10:21:43.000000000 -0700
|
||||
+++ newlib/libc/stdio/nano-vfprintf_local.h 2015-07-17 12:51:12.974269921 -0700
|
||||
@@ -230,5 +230,5 @@ _printf_float (struct _reent *data,
|
||||
FILE *fp,
|
||||
int (*pfunc)(struct _reent *, FILE *,
|
||||
_CONST char *, size_t len),
|
||||
- va_list *ap) _ATTRIBUTE((__weak__));
|
||||
+ va_list *ap);
|
||||
#endif
|
||||
--- newlib/libc/stdio/nano-vfscanf_local.h 2014-07-04 10:21:44.000000000 -0700
|
||||
+++ newlib/libc/stdio/nano-vfscanf_local.h 2015-07-17 12:51:33.967362409 -0700
|
||||
@@ -173,6 +173,6 @@ _scanf_i (struct _reent *rptr,
|
||||
extern int
|
||||
_scanf_float (struct _reent *rptr,
|
||||
struct _scan_data_t *pdata,
|
||||
- FILE *fp, va_list *ap) _ATTRIBUTE((__weak__));
|
||||
+ FILE *fp, va_list *ap);
|
||||
|
||||
#endif
|
|
@ -1,11 +0,0 @@
|
|||
source [find interface/ftdi/flyswatter2.cfg];
|
||||
source [find board/quark_x10xx_board.cfg];
|
||||
|
||||
quark_x10xx.cpu configure -event gdb-attach {
|
||||
halt
|
||||
}
|
||||
|
||||
quark_x10xx.cpu configure -event gdb-detach {
|
||||
resume
|
||||
shutdown
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CONTIKI_CONF_H
|
||||
#define CONTIKI_CONF_H
|
||||
|
||||
/* Include the default configuration file early here so that this file can
|
||||
* unconfigure the IP buffer size. That will allow uipopt.h to define a
|
||||
* default IP buffer size that is larger and more useful.
|
||||
*/
|
||||
#include "contiki-default-conf.h"
|
||||
|
||||
#undef UIP_CONF_BUFFER_SIZE
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#define CLOCK_CONF_SECOND 128
|
||||
typedef unsigned long clock_time_t;
|
||||
|
||||
typedef uint64_t rtimer_clock_t;
|
||||
#define RTIMER_ARCH_SECOND 1024
|
||||
#define RTIMER_CLOCK_DIFF(a, b) ((int64_t)((a) - (b)))
|
||||
|
||||
/* We define the following macros and types otherwise Contiki does not
|
||||
* compile.
|
||||
*/
|
||||
#define CCIF
|
||||
#define CLIF
|
||||
|
||||
#define UIP_CONF_LLH_LEN 14
|
||||
|
||||
#define UIP_CONF_LL_802154 0
|
||||
#define LINKADDR_CONF_SIZE 6
|
||||
|
||||
typedef unsigned short uip_stats_t;
|
||||
|
||||
#endif /* CONTIKI_CONF_H */
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "contiki.h"
|
||||
#include "contiki-net.h"
|
||||
#include "cpu.h"
|
||||
#include "eth.h"
|
||||
#include "eth-conf.h"
|
||||
#include "galileo-pinmux.h"
|
||||
#include "gpio.h"
|
||||
#include "helpers.h"
|
||||
#include "i2c.h"
|
||||
#include "imr-conf.h"
|
||||
#include "interrupt.h"
|
||||
#include "irq.h"
|
||||
#include "pci.h"
|
||||
#include "prot-domains.h"
|
||||
#include "shared-isr.h"
|
||||
#include "uart.h"
|
||||
|
||||
PROCINIT( &etimer_process
|
||||
, &tcpip_process
|
||||
#if WITH_DNS
|
||||
, &resolv_process
|
||||
#endif
|
||||
);
|
||||
|
||||
extern int _sdata_kern_startup_func, _edata_kern_startup_func;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
app_main(void)
|
||||
{
|
||||
printf("Starting Contiki\n");
|
||||
|
||||
process_init();
|
||||
procinit_init();
|
||||
ctimer_init();
|
||||
eth_init();
|
||||
|
||||
autostart_start(autostart_processes);
|
||||
|
||||
while(1) {
|
||||
process_run();
|
||||
}
|
||||
|
||||
halt();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
gp_fault_handler(struct interrupt_context context)
|
||||
{
|
||||
fprintf(stderr, "General protection exception @%08x (ec: %u)\n",
|
||||
context.eip, context.error_code);
|
||||
halt();
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* Kernel entrypoint */
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
uintptr_t *func_ptr;
|
||||
|
||||
#ifdef X86_CONF_RESTRICT_DMA
|
||||
quarkX1000_imr_conf();
|
||||
#endif
|
||||
irq_init();
|
||||
quarkX1000_uart_init();
|
||||
/* Initialize UART connected to Galileo Gen1 3.5mm audio-style jack or
|
||||
* Galileo Gen2 FTDI header
|
||||
*/
|
||||
quarkX1000_uart_init_port(QUARK_X1000_UART_1, 115200);
|
||||
SET_EXCEPTION_HANDLER(13, 1, gp_fault_handler);
|
||||
clock_init();
|
||||
rtimer_init();
|
||||
|
||||
pci_root_complex_init();
|
||||
quarkX1000_eth_init();
|
||||
quarkX1000_i2c_init();
|
||||
quarkX1000_i2c_configure(QUARKX1000_I2C_SPEED_STANDARD,
|
||||
QUARKX1000_I2C_ADDR_MODE_7BIT);
|
||||
/* The GPIO subsystem must be initialized prior to configuring pinmux, because
|
||||
* the pinmux configuration automatically performs GPIO configuration for the
|
||||
* relevant pins.
|
||||
*/
|
||||
quarkX1000_gpio_init();
|
||||
/* use default pinmux configuration */
|
||||
if(galileo_pinmux_initialize() < 0) {
|
||||
fprintf(stderr, "Failed to initialize pinmux\n");
|
||||
}
|
||||
shared_isr_init();
|
||||
|
||||
/* The ability to remap interrupts is not needed after this point and should
|
||||
* thus be disabled according to the principle of least privilege.
|
||||
*/
|
||||
pci_root_complex_lock();
|
||||
|
||||
func_ptr = (uintptr_t *)&_sdata_kern_startup_func;
|
||||
while(func_ptr != (uintptr_t *)&_edata_kern_startup_func) {
|
||||
((void (*)(void))*func_ptr)();
|
||||
|
||||
func_ptr++;
|
||||
}
|
||||
|
||||
prot_domains_leave_main();
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "sys/clock.h"
|
||||
#include "sys/etimer.h"
|
||||
|
||||
#include "contiki-conf.h"
|
||||
#include "drivers/legacy_pc/rtc.h"
|
||||
|
||||
#if CLOCK_CONF_SECOND == 2
|
||||
#define FREQ RTC_2_HZ
|
||||
#elif CLOCK_CONF_SECOND == 4
|
||||
#define FREQ RTC_4_HZ
|
||||
#elif CLOCK_CONF_SECOND == 8
|
||||
#define FREQ RTC_8_HZ
|
||||
#elif CLOCK_CONF_SECOND == 16
|
||||
#define FREQ RTC_16_HZ
|
||||
#elif CLOCK_CONF_SECOND == 32
|
||||
#define FREQ RTC_32_HZ
|
||||
#elif CLOCK_CONF_SECOND == 64
|
||||
#define FREQ RTC_64_HZ
|
||||
#elif CLOCK_CONF_SECOND == 128
|
||||
#define FREQ RTC_128_HZ
|
||||
#elif CLOCK_CONF_SECOND == 256
|
||||
#define FREQ RTC_256_HZ
|
||||
#elif CLOCK_CONF_SECOND == 512
|
||||
#define FREQ RTC_512_HZ
|
||||
#elif CLOCK_CONF_SECOND == 1024
|
||||
#define FREQ RTC_1024_HZ
|
||||
#elif CLOCK_CONF_SECOND == 2048
|
||||
#define FREQ RTC_2048_HZ
|
||||
#elif CLOCK_CONF_SECOND == 4096
|
||||
#define FREQ RTC_4096_HZ
|
||||
#elif CLOCK_CONF_SECOND == 8192
|
||||
#define FREQ RTC_8192_HZ
|
||||
#else
|
||||
#define FREQ -1
|
||||
#error "RTC is being used thus CLOCK_CONF_SECOND has to be a value defined by rtc_frequency_t."
|
||||
#endif
|
||||
|
||||
static volatile clock_time_t tick_count = 0;
|
||||
|
||||
static void
|
||||
update_ticks(void)
|
||||
{
|
||||
clock_time_t expire = etimer_next_expiration_time();
|
||||
|
||||
tick_count++;
|
||||
|
||||
/* Notify etimer library if the next event timer has expired */
|
||||
if(expire != 0 && tick_count >= expire) {
|
||||
etimer_request_poll();
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
clock_init(void)
|
||||
{
|
||||
rtc_init(FREQ, update_ticks);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
clock_time_t
|
||||
clock_time(void)
|
||||
{
|
||||
return tick_count;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
unsigned long
|
||||
clock_seconds(void)
|
||||
{
|
||||
return tick_count / CLOCK_CONF_SECOND;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
clock_wait(clock_time_t t)
|
||||
{
|
||||
clock_time_t initial = tick_count;
|
||||
|
||||
while(tick_count < t + initial);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
clock_set_seconds(unsigned long sec)
|
||||
{
|
||||
/* Stubbed function */
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
clock_delay_usec(uint16_t t)
|
||||
{
|
||||
/* Stubbed function */
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef MTARCH_H_
|
||||
#define MTARCH_H_
|
||||
|
||||
struct mtarch_thread {
|
||||
};
|
||||
|
||||
#endif /* MTARCH_H_ */
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "sys/rtimer.h"
|
||||
|
||||
#include "contiki-conf.h"
|
||||
#include "drivers/legacy_pc/pit.h"
|
||||
|
||||
static volatile rtimer_clock_t tick_count = 0;
|
||||
static rtimer_clock_t trigger = UINT64_MAX;
|
||||
|
||||
static void
|
||||
update_ticks(void)
|
||||
{
|
||||
if(++tick_count >= trigger) {
|
||||
/* Disable trigger by assigning it to the maximum value */
|
||||
trigger = UINT64_MAX;
|
||||
rtimer_run_next();
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
rtimer_arch_init(void)
|
||||
{
|
||||
pit_init(RTIMER_ARCH_SECOND, update_ticks);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
rtimer_clock_t
|
||||
rtimer_arch_now()
|
||||
{
|
||||
return tick_count;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
rtimer_arch_schedule(rtimer_clock_t t)
|
||||
{
|
||||
trigger = t;
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef RTIMER_ARCH_H
|
||||
#define RTIMER_ARCH_H
|
||||
|
||||
rtimer_clock_t rtimer_arch_now();
|
||||
|
||||
#endif /* RTIMER_ARCH_H */
|
|
@ -1,131 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "cy8c9540a.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "i2c.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* Change this to 0x21 if J2 is set to 1-2
|
||||
* (covering the pin marked with the white triangle). */
|
||||
#define I2C_ADDR 0x20
|
||||
|
||||
#define REG_PORT_SEL 0x18
|
||||
#define REG_PORT_DIR 0x1C
|
||||
|
||||
#define PORT_CNT 6
|
||||
|
||||
/* Cache the current state of each port to obviate the need for reading before
|
||||
* writing to output ports when simply updating a single pin.
|
||||
*/
|
||||
static uint8_t out_cache[PORT_CNT];
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
write_reg(uint8_t reg, uint8_t data)
|
||||
{
|
||||
uint8_t pkt[] = { reg, data };
|
||||
assert(quarkX1000_i2c_polling_write(pkt, sizeof(pkt), I2C_ADDR) == 0);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static uint8_t
|
||||
read_reg(uint8_t reg)
|
||||
{
|
||||
uint8_t data;
|
||||
assert(quarkX1000_i2c_polling_write(®, 1, I2C_ADDR) == 0);
|
||||
assert(quarkX1000_i2c_polling_read(&data, 1, I2C_ADDR) == 0);
|
||||
return data;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
cy8c9540a_init(void)
|
||||
{
|
||||
uint8_t status;
|
||||
|
||||
/* has to init after I2C master */
|
||||
assert(quarkX1000_i2c_is_available());
|
||||
|
||||
status = read_reg(0x2E);
|
||||
if((status >> 4) != 4) {
|
||||
fprintf(stderr, "Failed to communicate with CY8C9540A. Perhaps jumper J2 "
|
||||
"is not set to 2-3? Halting.\n");
|
||||
halt();
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Set the direction (in or out) for the indicated GPIO pin.
|
||||
*/
|
||||
void
|
||||
cy8c9540a_set_port_dir(cy8c9540a_bit_addr_t addr, cy8c9540a_port_dir_t dir)
|
||||
{
|
||||
uint8_t mask;
|
||||
|
||||
assert(addr.port < PORT_CNT);
|
||||
|
||||
write_reg(REG_PORT_SEL, addr.port);
|
||||
mask = read_reg(REG_PORT_DIR);
|
||||
mask &= ~(1 << addr.pin);
|
||||
mask |= ((uint8_t)dir) << addr.pin;
|
||||
write_reg(REG_PORT_DIR, mask);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* \brief Set the drive mode for the indicated GPIO pin.
|
||||
*/
|
||||
void
|
||||
cy8c9540a_set_drive_mode(cy8c9540a_bit_addr_t addr,
|
||||
cy8c9540a_drive_mode_t drv_mode)
|
||||
{
|
||||
assert(addr.port < PORT_CNT);
|
||||
|
||||
write_reg(REG_PORT_SEL, addr.port);
|
||||
write_reg((uint8_t)drv_mode, 1 << addr.pin);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
bool
|
||||
cy8c9540a_read(cy8c9540a_bit_addr_t addr)
|
||||
{
|
||||
assert(addr.port < PORT_CNT);
|
||||
|
||||
return ((read_reg(addr.port) >> addr.pin) & 1) == 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
cy8c9540a_write(cy8c9540a_bit_addr_t addr, bool val)
|
||||
{
|
||||
assert(addr.port < PORT_CNT);
|
||||
|
||||
out_cache[addr.port] &= ~(1 << addr.pin);
|
||||
out_cache[addr.port] |= ((uint8_t)val) << addr.pin;
|
||||
write_reg(8 + addr.port, out_cache[addr.port]);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,72 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_GALILEO_DRIVERS_CY8C9540A_H_
|
||||
#define PLATFORM_GALILEO_DRIVERS_CY8C9540A_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Driver for Cypress Semiconductors CY8C9540A device used for GPIO, PWM, and
|
||||
* pinmuxing on the first generation Intel Galileo.
|
||||
*/
|
||||
|
||||
/* The numeric value of each drive mode corresponds to the device register
|
||||
* address for selecting that mode. Only a subset of the available modes are
|
||||
* listed here.
|
||||
*/
|
||||
typedef enum cy8c9540a_drive_mode {
|
||||
CY8C9540A_DRIVE_PULL_UP = 0x1D,
|
||||
CY8C9540A_DRIVE_PULL_DOWN = 0x1E,
|
||||
CY8C9540A_DRIVE_STRONG = 0x21,
|
||||
CY8C9540A_DRIVE_HI_Z = 0x23
|
||||
} cy8c9540a_drive_mode_t;
|
||||
|
||||
typedef enum cy8c9540a_port_dir {
|
||||
CY8C9540A_PORT_DIR_OUT = 0,
|
||||
CY8C9540A_PORT_DIR_IN = 1
|
||||
} cy8c9540a_port_dir_t;
|
||||
|
||||
typedef struct cy8c9540a_bit_addr {
|
||||
uint8_t port;
|
||||
int pin;
|
||||
} cy8c9540a_bit_addr_t;
|
||||
|
||||
#define CY8C9540A_BIT_ADDR_INVALID_PORT 0xFF
|
||||
|
||||
void cy8c9540a_init(void);
|
||||
void cy8c9540a_set_port_dir(cy8c9540a_bit_addr_t addr,
|
||||
cy8c9540a_port_dir_t dir);
|
||||
void cy8c9540a_set_drive_mode(cy8c9540a_bit_addr_t addr,
|
||||
cy8c9540a_drive_mode_t drv_mode);
|
||||
bool cy8c9540a_read(cy8c9540a_bit_addr_t addr);
|
||||
void cy8c9540a_write(cy8c9540a_bit_addr_t addr, bool val);
|
||||
|
||||
#endif /* PLATFORM_GALILEO_DRIVERS_CY8C9540A_H_ */
|
|
@ -1,282 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "galileo-pinmux.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "cy8c9540a.h"
|
||||
#include "gpio.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static cy8c9540a_bit_addr_t mux_bit_addrs[] = {
|
||||
{ 3, 4 }, /* IO0 */
|
||||
{ 3, 5 }, /* IO1 */
|
||||
{ 1, 7 }, /* IO2 */
|
||||
{ 1, 6 }, /* IO3 */
|
||||
{ CY8C9540A_BIT_ADDR_INVALID_PORT, 0 }, /* IO4 */
|
||||
{ CY8C9540A_BIT_ADDR_INVALID_PORT, 0 }, /* IO5 */
|
||||
{ CY8C9540A_BIT_ADDR_INVALID_PORT, 0 }, /* IO6 */
|
||||
{ CY8C9540A_BIT_ADDR_INVALID_PORT, 0 }, /* IO7 */
|
||||
{ CY8C9540A_BIT_ADDR_INVALID_PORT, 0 }, /* IO8 */
|
||||
{ CY8C9540A_BIT_ADDR_INVALID_PORT, 0 }, /* IO9 */
|
||||
{ 3, 6 }, /* IO10 */
|
||||
{ 3, 7 }, /* IO11 */
|
||||
{ 5, 2 }, /* IO12 */
|
||||
{ 5, 3 }, /* IO13 */
|
||||
{ 3, 1 }, /* A0 */
|
||||
{ 3, 0 }, /* A1 */
|
||||
{ 0, 7 }, /* A2 */
|
||||
{ 0, 6 }, /* A3 */
|
||||
{ 0, 5 }, /* A4 (also controlled by I2C mux) */
|
||||
{ 0, 4 }, /* A5 (also controlled by I2C mux) */
|
||||
};
|
||||
|
||||
static cy8c9540a_bit_addr_t i2c_mux_bit_addr = { 1, 5 };
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
flatten_pin_num(galileo_pin_group_t grp, unsigned *pin)
|
||||
{
|
||||
if(grp == GALILEO_PIN_GRP_ANALOG) {
|
||||
*pin += GALILEO_NUM_DIGITAL_PINS;
|
||||
}
|
||||
|
||||
assert(*pin < GALILEO_NUM_PINS);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* See galileo-gpio.c for the declaration of this function. */
|
||||
int
|
||||
galileo_brd_to_cpu_gpio_pin(unsigned pin, bool *sus)
|
||||
{
|
||||
assert(pin < GALILEO_NUM_PINS);
|
||||
*sus = false;
|
||||
switch(pin) {
|
||||
case 2:
|
||||
return 6;
|
||||
case 3:
|
||||
return 7;
|
||||
case 10:
|
||||
return 2;
|
||||
default:
|
||||
return -1; /* GPIO pin may be connected to the CY8C9540A chip, but not the
|
||||
CPU. */
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static cy8c9540a_bit_addr_t cy8c9540a_gpio_mapping[] = {
|
||||
{ 4, 6 },
|
||||
{ 4, 7 },
|
||||
{ CY8C9540A_BIT_ADDR_INVALID_PORT, 0 },
|
||||
{ CY8C9540A_BIT_ADDR_INVALID_PORT, 0 },
|
||||
{ 1, 4 },
|
||||
{ 0, 1 },
|
||||
{ 1, 0 },
|
||||
{ 1, 3 },
|
||||
{ 1, 2 },
|
||||
{ 0, 3 },
|
||||
{ 0, 0 }, /* This driver configures IO10 to connect to CPU GPIO when setting
|
||||
IO10 to a digital mode, but hardware exists to alternately
|
||||
connect it to this pin of the CY8C9540A chip. */
|
||||
{ 1, 1 },
|
||||
{ 3, 2 },
|
||||
{ 3, 3 },
|
||||
{ 4, 0 },
|
||||
{ 4, 1 },
|
||||
{ 4, 2 },
|
||||
{ 4, 3 },
|
||||
{ 4, 4 },
|
||||
{ 4, 5 }
|
||||
};
|
||||
/* Map a board-level GPIO pin number to the address of the CY8C9540A pin that
|
||||
* implements it.
|
||||
*/
|
||||
cy8c9540a_bit_addr_t
|
||||
galileo_brd_to_cy8c9540a_gpio_pin(unsigned pin)
|
||||
{
|
||||
assert(pin < GALILEO_NUM_PINS);
|
||||
return cy8c9540a_gpio_mapping[pin];
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/* The I2C mux control must be set high to be able to access A4 and A5.
|
||||
*/
|
||||
static void
|
||||
set_i2c_mux(bool val)
|
||||
{
|
||||
cy8c9540a_write(i2c_mux_bit_addr, val);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
select_gpio_pwm(unsigned flat_pin, bool pwm)
|
||||
{
|
||||
bool mux_val;
|
||||
cy8c9540a_bit_addr_t mux_bit_addr;
|
||||
mux_bit_addr = mux_bit_addrs[flat_pin];
|
||||
if(mux_bit_addr.port != CY8C9540A_BIT_ADDR_INVALID_PORT) {
|
||||
mux_val = pwm || !(flat_pin == 2 || flat_pin == 3 || flat_pin == 10);
|
||||
cy8c9540a_write(mux_bit_addr, mux_val);
|
||||
}
|
||||
if((GALILEO_NUM_DIGITAL_PINS + 4) <= flat_pin) {
|
||||
/* This single control switches away from both I2C pins. */
|
||||
set_i2c_mux(true);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void
|
||||
select_gpio(galileo_pin_group_t grp, unsigned pin, bool out)
|
||||
{
|
||||
bool sus;
|
||||
int cpu_pin;
|
||||
cy8c9540a_bit_addr_t gpio_bit_addr;
|
||||
|
||||
flatten_pin_num(grp, &pin);
|
||||
select_gpio_pwm(pin, false);
|
||||
|
||||
cpu_pin = galileo_brd_to_cpu_gpio_pin(pin, &sus);
|
||||
if(cpu_pin == -1) {
|
||||
gpio_bit_addr = galileo_brd_to_cy8c9540a_gpio_pin(pin);
|
||||
cy8c9540a_set_port_dir(gpio_bit_addr,
|
||||
out?
|
||||
CY8C9540A_PORT_DIR_OUT :
|
||||
CY8C9540A_PORT_DIR_IN);
|
||||
cy8c9540a_set_drive_mode(gpio_bit_addr,
|
||||
out?
|
||||
CY8C9540A_DRIVE_STRONG :
|
||||
CY8C9540A_DRIVE_HI_Z);
|
||||
} else {
|
||||
quarkX1000_gpio_config(cpu_pin,
|
||||
out? QUARKX1000_GPIO_OUT : QUARKX1000_GPIO_IN);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void
|
||||
galileo_pinmux_select_din(galileo_pin_group_t grp, unsigned pin)
|
||||
{
|
||||
select_gpio(grp, pin, false);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void galileo_pinmux_select_dout(galileo_pin_group_t grp, unsigned pin)
|
||||
{
|
||||
select_gpio(grp, pin, true);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void galileo_pinmux_select_pwm(unsigned pin)
|
||||
{
|
||||
switch(pin) {
|
||||
case 3:
|
||||
case 5:
|
||||
case 6:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: invalid pin: %d.\n", __FUNCTION__, pin);
|
||||
halt();
|
||||
}
|
||||
|
||||
select_gpio_pwm(pin, true);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void galileo_pinmux_select_serial(unsigned pin)
|
||||
{
|
||||
assert(pin == 0 || pin == 1);
|
||||
|
||||
cy8c9540a_write(mux_bit_addrs[pin], false);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void galileo_pinmux_select_i2c(void)
|
||||
{
|
||||
set_i2c_mux(false);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void galileo_pinmux_select_spi(void)
|
||||
{
|
||||
unsigned pin;
|
||||
for(pin = 11; pin <= 13; pin++) {
|
||||
cy8c9540a_write(mux_bit_addrs[pin], false);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
void galileo_pinmux_select_analog(unsigned pin)
|
||||
{
|
||||
assert(pin < GALILEO_NUM_ANALOG_PINS);
|
||||
pin += GALILEO_NUM_DIGITAL_PINS;
|
||||
|
||||
cy8c9540a_write(mux_bit_addrs[pin], false);
|
||||
|
||||
if(4 <= pin) {
|
||||
/* This single control switches away from both I2C pins. */
|
||||
set_i2c_mux(true);
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int
|
||||
galileo_pinmux_initialize(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
cy8c9540a_init();
|
||||
|
||||
/* Configure all mux control pins as outputs. */
|
||||
for(i = 0; i < GALILEO_NUM_PINS; i++) {
|
||||
if(mux_bit_addrs[i].port == CY8C9540A_BIT_ADDR_INVALID_PORT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cy8c9540a_set_port_dir(mux_bit_addrs[i], CY8C9540A_PORT_DIR_OUT);
|
||||
cy8c9540a_set_drive_mode(mux_bit_addrs[i], CY8C9540A_DRIVE_STRONG);
|
||||
}
|
||||
cy8c9540a_set_port_dir(i2c_mux_bit_addr, CY8C9540A_PORT_DIR_OUT);
|
||||
cy8c9540a_set_drive_mode(i2c_mux_bit_addr, CY8C9540A_DRIVE_STRONG);
|
||||
|
||||
/* Activate default pinmux configuration. */
|
||||
galileo_pinmux_select_serial(0);
|
||||
galileo_pinmux_select_serial(1);
|
||||
galileo_pinmux_select_dout(GALILEO_PIN_GRP_DIGITAL, 2);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 3);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 4);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 5);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 6);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 7);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 8);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 9);
|
||||
galileo_pinmux_select_dout(GALILEO_PIN_GRP_DIGITAL, 10);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 11);
|
||||
galileo_pinmux_select_dout(GALILEO_PIN_GRP_DIGITAL, 12);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 13);
|
||||
galileo_pinmux_select_analog(0);
|
||||
galileo_pinmux_select_analog(1);
|
||||
galileo_pinmux_select_analog(2);
|
||||
galileo_pinmux_select_analog(3);
|
||||
galileo_pinmux_select_i2c();
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
|
@ -1,724 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "galileo-pinmux.h"
|
||||
#include <assert.h>
|
||||
#include "gpio.h"
|
||||
#include "gpio-pcal9535a.h"
|
||||
#include "i2c.h"
|
||||
#include "pwm-pca9685.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef enum {
|
||||
GALILEO_PINMUX_FUNC_A,
|
||||
GALILEO_PINMUX_FUNC_B,
|
||||
GALILEO_PINMUX_FUNC_C,
|
||||
GALILEO_PINMUX_FUNC_D
|
||||
} GALILEO_PINMUX_FUNC;
|
||||
|
||||
#define GPIO_PCAL9535A_0_I2C_ADDR 0x25
|
||||
#define GPIO_PCAL9535A_1_I2C_ADDR 0x26
|
||||
#define GPIO_PCAL9535A_2_I2C_ADDR 0x27
|
||||
#define PWM_PCA9685_0_I2C_ADDR 0x47
|
||||
|
||||
#define PINMUX_NUM_FUNCS 4
|
||||
#define PINMUX_NUM_PATHS 4
|
||||
|
||||
typedef enum {
|
||||
NONE,
|
||||
EXP0,
|
||||
EXP1,
|
||||
EXP2,
|
||||
PWM0
|
||||
} MUX_CHIP;
|
||||
|
||||
typedef enum {
|
||||
PIN_LOW = 0x00,
|
||||
PIN_HIGH = 0x01,
|
||||
DISABLED = 0xFF
|
||||
} PIN_LEVEL;
|
||||
|
||||
struct pin_config {
|
||||
uint8_t pin_num;
|
||||
GALILEO_PINMUX_FUNC func;
|
||||
};
|
||||
|
||||
struct mux_pin {
|
||||
MUX_CHIP chip;
|
||||
uint8_t pin;
|
||||
PIN_LEVEL level;
|
||||
uint32_t cfg;
|
||||
};
|
||||
|
||||
struct mux_path {
|
||||
uint8_t io_pin;
|
||||
GALILEO_PINMUX_FUNC func;
|
||||
struct mux_pin path[PINMUX_NUM_PATHS];
|
||||
};
|
||||
|
||||
struct pinmux_internal_data {
|
||||
struct gpio_pcal9535a_data exp0;
|
||||
struct gpio_pcal9535a_data exp1;
|
||||
struct gpio_pcal9535a_data exp2;
|
||||
struct pwm_pca9685_data pwm0;
|
||||
};
|
||||
|
||||
static struct pinmux_internal_data data;
|
||||
|
||||
static struct mux_path galileo_pinmux_paths[GALILEO_NUM_PINS * PINMUX_NUM_FUNCS] = {
|
||||
{0, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP1, 0, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* GPIO3 out */
|
||||
{ EXP1, 1, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{0, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP1, 0, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO3 in */
|
||||
{ EXP1, 1, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{0, GALILEO_PINMUX_FUNC_C, {
|
||||
{ EXP1, 0, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* UART0_RXD */
|
||||
{ EXP1, 1, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{0, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{1, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP1, 13, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO4 out */
|
||||
{ EXP0, 12, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 13, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{1, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP1, 13, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO4 in */
|
||||
{ EXP0, 12, PIN_HIGH, (QUARKX1000_GPIO_OUT)},
|
||||
{ EXP0, 13, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{1, GALILEO_PINMUX_FUNC_C, {
|
||||
{ EXP1, 13, PIN_HIGH, (QUARKX1000_GPIO_OUT)}, /* UART0_TXD */
|
||||
{ EXP0, 12, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 13, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{1, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{2, GALILEO_PINMUX_FUNC_A, {
|
||||
{ PWM0, 13, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* GPIO5 out */
|
||||
{ EXP1, 2, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP1, 3, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{2, GALILEO_PINMUX_FUNC_B, {
|
||||
{ PWM0, 13, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* GPIO5 in */
|
||||
{ EXP1, 2, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP1, 3, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{2, GALILEO_PINMUX_FUNC_C, {
|
||||
{ PWM0, 13, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* UART1_RXD */
|
||||
{ EXP1, 2, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP1, 3, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{2, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{3, GALILEO_PINMUX_FUNC_A, {
|
||||
{ PWM0, 0, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO6 out */
|
||||
{ PWM0, 12, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 0, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 1, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
{3, GALILEO_PINMUX_FUNC_B, {
|
||||
{ PWM0, 0, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO6 in */
|
||||
{ PWM0, 12, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 0, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 1, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
{3, GALILEO_PINMUX_FUNC_C, {
|
||||
{ PWM0, 0, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* UART1_TXD */
|
||||
{ PWM0, 12, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 0, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 1, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
{3, GALILEO_PINMUX_FUNC_D, {
|
||||
{ PWM0, 0, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* PWM.LED1 */
|
||||
{ PWM0, 12, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 0, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 1, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
|
||||
{4, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP1, 4, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO_SUS4 out */
|
||||
{ EXP1, 5, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{4, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP1, 4, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* GPIO_SUS4 in */
|
||||
{ EXP1, 5, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{4, GALILEO_PINMUX_FUNC_C, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{4, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{5, GALILEO_PINMUX_FUNC_A, {
|
||||
{ PWM0, 2, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO8 (out) */
|
||||
{ EXP0, 2, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 3, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{5, GALILEO_PINMUX_FUNC_B, {
|
||||
{ PWM0, 2, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO8 (in) */
|
||||
{ EXP0, 2, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 3, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{5, GALILEO_PINMUX_FUNC_C, {
|
||||
{ PWM0, 2, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* PWM.LED3 */
|
||||
{ EXP0, 2, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 3, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{5, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{6, GALILEO_PINMUX_FUNC_A, {
|
||||
{ PWM0, 4, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO9 (out) */
|
||||
{ EXP0, 4, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 5, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{6, GALILEO_PINMUX_FUNC_B, {
|
||||
{ PWM0, 4, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO9 (in) */
|
||||
{ EXP0, 4, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 5, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{6, GALILEO_PINMUX_FUNC_C, {
|
||||
{ PWM0, 4, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* PWM.LED5 */
|
||||
{ EXP0, 4, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 5, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{6, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{7, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP1, 6, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO_SUS0 (out) */
|
||||
{ EXP1, 7, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{7, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP1, 6, PIN_LOW, (QUARKX1000_GPIO_IN ) }, /* GPIO_SUS0 (in) */
|
||||
{ EXP1, 7, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{7, GALILEO_PINMUX_FUNC_C, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{7, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{8, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP1, 8, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO_SUS1 (out) */
|
||||
{ EXP1, 9, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{8, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP1, 8, PIN_LOW, (QUARKX1000_GPIO_IN ) }, /* GPIO_SUS1 (in) */
|
||||
{ EXP1, 9, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{8, GALILEO_PINMUX_FUNC_C, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{8, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{9, GALILEO_PINMUX_FUNC_A, {
|
||||
{ PWM0, 6, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO_SUS2 (out) */
|
||||
{ EXP0, 6, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 7, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{9, GALILEO_PINMUX_FUNC_B, {
|
||||
{ PWM0, 6, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO_SUS2 (in) */
|
||||
{ EXP0, 6, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 7, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{9, GALILEO_PINMUX_FUNC_C, {
|
||||
{ PWM0, 6, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* PWM.LED7 */
|
||||
{ EXP0, 6, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 7, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{9, GALILEO_PINMUX_FUNC_C, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{10, GALILEO_PINMUX_FUNC_A, {
|
||||
{ PWM0, 10, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO2 (out) */
|
||||
{ EXP0, 10, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 11, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{10, GALILEO_PINMUX_FUNC_B, {
|
||||
{ PWM0, 10, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO2 (in) */
|
||||
{ EXP0, 10, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 11, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{10, GALILEO_PINMUX_FUNC_C, {
|
||||
{ PWM0, 10, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* PWM.LED11 */
|
||||
{ EXP0, 10, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 11, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{10, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{11, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP1, 12, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO_SUS3 (out) */
|
||||
{ PWM0, 8, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 8, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 9, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
{11, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP1, 12, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO_SUS3 (in) */
|
||||
{ PWM0, 8, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 8, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 9, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
{11, GALILEO_PINMUX_FUNC_C, {
|
||||
{ EXP1, 12, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* PWM.LED9 */
|
||||
{ PWM0, 8, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 8, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 9, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
{11, GALILEO_PINMUX_FUNC_D, {
|
||||
{ EXP1, 12, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* SPI1_MOSI */
|
||||
{ PWM0, 8, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 8, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 9, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
|
||||
{12, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP1, 10, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO7 (out) */
|
||||
{ EXP1, 11, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{12, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP1, 10, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* GPIO7 (in) */
|
||||
{ EXP1, 11, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{12, GALILEO_PINMUX_FUNC_C, {
|
||||
{ EXP1, 10, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* SPI1_MISO */
|
||||
{ EXP1, 11, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{12, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{13, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP1, 14, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO_SUS5 (out) */
|
||||
{ EXP0, 14, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 15, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{13, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP1, 14, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* GPIO_SUS5 (in) */
|
||||
{ EXP0, 14, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 15, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{13, GALILEO_PINMUX_FUNC_C, {
|
||||
{ EXP1, 14, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* SPI1_CLK */
|
||||
{ EXP0, 14, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP0, 15, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{13, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{14, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP2, 0, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* EXP2.P0_0 (out)/ADC.IN0 */
|
||||
{ EXP2, 1, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{14, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP2, 0, PIN_LOW, (QUARKX1000_GPIO_IN ) }, /* EXP2.P0_0 (in)/ADC.IN0 */
|
||||
{ EXP2, 1, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{14, GALILEO_PINMUX_FUNC_C, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{14, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{15, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP2, 2, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* EXP2.P0_2 (out)/ADC.IN1 */
|
||||
{ EXP2, 3, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{15, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP2, 2, PIN_LOW, (QUARKX1000_GPIO_IN ) }, /* EXP2.P0_2 (in)/ADC.IN1 */
|
||||
{ EXP2, 3, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{15, GALILEO_PINMUX_FUNC_C, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{15, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{16, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP2, 4, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* EXP2.P0_4 (out)/ADC.IN2 */
|
||||
{ EXP2, 5, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{16, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP2, 4, PIN_LOW, (QUARKX1000_GPIO_IN ) }, /* EXP2.P0_4 (in)/ADC.IN2 */
|
||||
{ EXP2, 5, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{16, GALILEO_PINMUX_FUNC_C, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{16, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{17, GALILEO_PINMUX_FUNC_A, {
|
||||
{ EXP2, 6, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* EXP2.P0_6 (out)/ADC.IN3 */
|
||||
{ EXP2, 7, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{17, GALILEO_PINMUX_FUNC_B, {
|
||||
{ EXP2, 6, PIN_LOW, (QUARKX1000_GPIO_IN ) }, /* EXP2.P0_6 (in)/ADC.IN3 */
|
||||
{ EXP2, 7, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{17, GALILEO_PINMUX_FUNC_C, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{17, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{18, GALILEO_PINMUX_FUNC_A, {
|
||||
{ PWM0, 14, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* EXP2.P1_0 (out)/ADC.IN4 */
|
||||
{ EXP2, 12, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP2, 8, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP2, 9, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
{18, GALILEO_PINMUX_FUNC_B, {
|
||||
{ PWM0, 14, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* EXP2.P1_0 (in)/ADC.IN4 */
|
||||
{ EXP2, 12, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP2, 8, PIN_LOW, (QUARKX1000_GPIO_IN ) },
|
||||
{ EXP2, 9, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
{18, GALILEO_PINMUX_FUNC_C, {
|
||||
{ PWM0, 14, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* I2C SDA */
|
||||
{ EXP2, 9, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP2, 12, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{18, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
|
||||
{19, GALILEO_PINMUX_FUNC_A, {
|
||||
{ PWM0, 15, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* EXP2.P1_2 (out)/ADC.IN5 */
|
||||
{ EXP2, 12, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP2, 10, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP2, 11, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
{19, GALILEO_PINMUX_FUNC_B, {
|
||||
{ PWM0, 15, PIN_LOW, (QUARKX1000_GPIO_OUT) }, /* EXP2.P1_2 (in)/ADC.IN5 */
|
||||
{ EXP2, 12, PIN_HIGH, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP2, 10, PIN_LOW, (QUARKX1000_GPIO_IN ) },
|
||||
{ EXP2, 11, PIN_LOW, (QUARKX1000_GPIO_OUT) }}},
|
||||
{19, GALILEO_PINMUX_FUNC_C, {
|
||||
{ PWM0, 15, PIN_HIGH, (QUARKX1000_GPIO_OUT) }, /* I2C SCL */
|
||||
{ EXP2, 11, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ EXP2, 12, PIN_LOW, (QUARKX1000_GPIO_OUT) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
{19, GALILEO_PINMUX_FUNC_D, {
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }, /* NONE */
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) },
|
||||
{ NONE, 0, DISABLED, (QUARKX1000_GPIO_IN ) }}},
|
||||
};
|
||||
|
||||
static int
|
||||
galileo_pinmux_set_pin(uint8_t pin, GALILEO_PINMUX_FUNC func)
|
||||
{
|
||||
struct mux_path *mux_path;
|
||||
uint8_t index, i;
|
||||
|
||||
if(pin >= GALILEO_NUM_PINS) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
index = PINMUX_NUM_FUNCS * pin;
|
||||
index += func;
|
||||
|
||||
mux_path = &galileo_pinmux_paths[index];
|
||||
|
||||
for(i = 0; i < PINMUX_NUM_PATHS; i++) {
|
||||
struct gpio_pcal9535a_data *exp = NULL;
|
||||
switch(mux_path->path[i].chip) {
|
||||
case EXP0:
|
||||
exp = &data.exp0;
|
||||
break;
|
||||
case EXP1:
|
||||
exp = &data.exp1;
|
||||
break;
|
||||
case EXP2:
|
||||
exp = &data.exp2;
|
||||
break;
|
||||
case PWM0:
|
||||
if(pwm_pca9685_set_duty_cycle(&data.pwm0, mux_path->path[i].pin, mux_path->path[i].level ? 100 : 0) < 0) {
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
case NONE:
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(exp != NULL);
|
||||
|
||||
if(gpio_pcal9535a_write(exp, mux_path->path[i].pin, mux_path->path[i].level) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if(gpio_pcal9535a_config(exp, mux_path->path[i].pin, mux_path->path[i].cfg) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static void
|
||||
flatten_pin_num(galileo_pin_group_t grp, unsigned *pin)
|
||||
{
|
||||
if(grp == GALILEO_PIN_GRP_ANALOG) {
|
||||
*pin += GALILEO_NUM_DIGITAL_PINS;
|
||||
}
|
||||
|
||||
assert(*pin < GALILEO_NUM_PINS);
|
||||
}
|
||||
/* See galileo-gpio.c for the declaration of this function. */
|
||||
int
|
||||
galileo_brd_to_cpu_gpio_pin(unsigned pin, bool *sus)
|
||||
{
|
||||
static const int SUS = 0x100;
|
||||
unsigned pins[GALILEO_NUM_DIGITAL_PINS] = {
|
||||
3, 4, 5, 6,
|
||||
SUS | 4, 8, 9, SUS | 0,
|
||||
SUS | 1, SUS | 2, 2, SUS | 3,
|
||||
7, SUS | 5
|
||||
};
|
||||
int cpu_pin;
|
||||
|
||||
/* GPIOs in the analog pin space are implemented by EXP2, not the CPU. */
|
||||
assert(pin < GALILEO_NUM_DIGITAL_PINS);
|
||||
cpu_pin = pins[pin];
|
||||
|
||||
*sus = (cpu_pin & SUS) == SUS;
|
||||
|
||||
return cpu_pin & ~SUS;
|
||||
}
|
||||
void
|
||||
galileo_pinmux_select_din(galileo_pin_group_t grp, unsigned pin)
|
||||
{
|
||||
bool sus;
|
||||
int cpu_pin;
|
||||
|
||||
flatten_pin_num(grp, &pin);
|
||||
|
||||
assert(galileo_pinmux_set_pin(pin, GALILEO_PINMUX_FUNC_B) == 0);
|
||||
|
||||
cpu_pin = galileo_brd_to_cpu_gpio_pin(pin, &sus);
|
||||
/* GPIO_SUS pins are currently unsupported. */
|
||||
assert(!sus);
|
||||
quarkX1000_gpio_config(cpu_pin, QUARKX1000_GPIO_IN);
|
||||
}
|
||||
void
|
||||
galileo_pinmux_select_dout(galileo_pin_group_t grp, unsigned pin)
|
||||
{
|
||||
bool sus;
|
||||
int cpu_pin;
|
||||
|
||||
flatten_pin_num(grp, &pin);
|
||||
|
||||
assert(galileo_pinmux_set_pin(pin, GALILEO_PINMUX_FUNC_A) == 0);
|
||||
|
||||
cpu_pin = galileo_brd_to_cpu_gpio_pin(pin, &sus);
|
||||
/* GPIO_SUS pins are currently unsupported. */
|
||||
assert(!sus);
|
||||
quarkX1000_gpio_config(cpu_pin, QUARKX1000_GPIO_OUT);
|
||||
}
|
||||
void
|
||||
galileo_pinmux_select_pwm(unsigned pin)
|
||||
{
|
||||
GALILEO_PINMUX_FUNC func = GALILEO_PINMUX_FUNC_C;
|
||||
switch(pin) {
|
||||
case 3:
|
||||
func = GALILEO_PINMUX_FUNC_D;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "%s: invalid pin: %d.\n", __FUNCTION__, pin);
|
||||
halt();
|
||||
}
|
||||
|
||||
assert(galileo_pinmux_set_pin(pin, func) == 0);
|
||||
}
|
||||
void
|
||||
galileo_pinmux_select_serial(unsigned pin)
|
||||
{
|
||||
assert(pin < 4);
|
||||
|
||||
assert(galileo_pinmux_set_pin(pin, GALILEO_PINMUX_FUNC_C) == 0);
|
||||
}
|
||||
void
|
||||
galileo_pinmux_select_i2c(void)
|
||||
{
|
||||
assert(galileo_pinmux_set_pin(18, GALILEO_PINMUX_FUNC_C) == 0);
|
||||
assert(galileo_pinmux_set_pin(19, GALILEO_PINMUX_FUNC_C) == 0);
|
||||
}
|
||||
void
|
||||
galileo_pinmux_select_spi(void)
|
||||
{
|
||||
assert(galileo_pinmux_set_pin(11, GALILEO_PINMUX_FUNC_D) == 0);
|
||||
assert(galileo_pinmux_set_pin(12, GALILEO_PINMUX_FUNC_C) == 0);
|
||||
assert(galileo_pinmux_set_pin(13, GALILEO_PINMUX_FUNC_C) == 0);
|
||||
}
|
||||
void
|
||||
galileo_pinmux_select_analog(unsigned pin)
|
||||
{
|
||||
assert(pin < GALILEO_NUM_ANALOG_PINS);
|
||||
|
||||
pin += GALILEO_NUM_DIGITAL_PINS;
|
||||
|
||||
assert(galileo_pinmux_set_pin(pin, GALILEO_PINMUX_FUNC_B) == 0);
|
||||
}
|
||||
int
|
||||
galileo_pinmux_initialize(void)
|
||||
{
|
||||
/* has to init after I2C master */
|
||||
if(!quarkX1000_i2c_is_available()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(gpio_pcal9535a_init(&data.exp0, GPIO_PCAL9535A_0_I2C_ADDR) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(gpio_pcal9535a_init(&data.exp1, GPIO_PCAL9535A_1_I2C_ADDR) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(gpio_pcal9535a_init(&data.exp2, GPIO_PCAL9535A_2_I2C_ADDR) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(pwm_pca9685_init(&data.pwm0, PWM_PCA9685_0_I2C_ADDR) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Activate default pinmux configuration. */
|
||||
/* Some of the following lines are commented out due to the GPIO_SUS pins
|
||||
* being currently unsupported.
|
||||
*/
|
||||
galileo_pinmux_select_serial(0);
|
||||
galileo_pinmux_select_serial(1);
|
||||
galileo_pinmux_select_dout(GALILEO_PIN_GRP_DIGITAL, 2);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 3);
|
||||
/*galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 4);*/
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 5);
|
||||
galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 6);
|
||||
/*galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 7);*/
|
||||
/*galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 8);*/
|
||||
/*galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 9);*/
|
||||
galileo_pinmux_select_dout(GALILEO_PIN_GRP_DIGITAL, 10);
|
||||
/*galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 11);*/
|
||||
galileo_pinmux_select_dout(GALILEO_PIN_GRP_DIGITAL, 12);
|
||||
/*galileo_pinmux_select_din(GALILEO_PIN_GRP_DIGITAL, 13);*/
|
||||
galileo_pinmux_select_analog(0);
|
||||
galileo_pinmux_select_analog(1);
|
||||
galileo_pinmux_select_analog(2);
|
||||
galileo_pinmux_select_analog(3);
|
||||
galileo_pinmux_select_i2c();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "galileo-gpio.h"
|
||||
#include <assert.h>
|
||||
#include "gpio.h"
|
||||
#if GALILEO_GEN == 1
|
||||
#include "cy8c9540a.h"
|
||||
#endif
|
||||
|
||||
/* Must be implemented in board-specific pinmux file to map a board-level GPIO
|
||||
* pin number to the corresponding CPU GPIO pin number.
|
||||
*
|
||||
* For gen. 1 boards, the value -1 may be returned to indicate that the
|
||||
* specified GPIO pin is not connected to any CPU pin. For gen. 2 boards, the
|
||||
* return value should always be a positive number. An assertion within the
|
||||
* function should check the validity of the pin number.
|
||||
*/
|
||||
int galileo_brd_to_cpu_gpio_pin(unsigned pin, bool *sus);
|
||||
#if GALILEO_GEN == 1
|
||||
cy8c9540a_bit_addr_t galileo_brd_to_cy8c9540a_gpio_pin(unsigned pin);
|
||||
#endif
|
||||
|
||||
static int
|
||||
brd_to_cpu_pin(unsigned pin)
|
||||
{
|
||||
int cpu_pin;
|
||||
bool sus;
|
||||
|
||||
cpu_pin = galileo_brd_to_cpu_gpio_pin(pin, &sus);
|
||||
assert(!sus);
|
||||
|
||||
return cpu_pin;
|
||||
}
|
||||
|
||||
void galileo_gpio_config(uint8_t pin, int flags)
|
||||
{
|
||||
assert(quarkX1000_gpio_config(brd_to_cpu_pin(pin), flags) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Read from GPIO.
|
||||
* \param pin Board-level IO pin number.
|
||||
*/
|
||||
void galileo_gpio_read(uint8_t pin, uint8_t *value)
|
||||
{
|
||||
#if GALILEO_GEN == 1
|
||||
cy8c9540a_bit_addr_t bit_addr;
|
||||
#endif
|
||||
int cpu_pin = brd_to_cpu_pin(pin);
|
||||
#if GALILEO_GEN == 1
|
||||
if(cpu_pin == -1) {
|
||||
bit_addr = galileo_brd_to_cy8c9540a_gpio_pin(pin);
|
||||
*value = cy8c9540a_read(bit_addr);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
assert(quarkX1000_gpio_read(cpu_pin, value) == 0);
|
||||
}
|
||||
|
||||
void galileo_gpio_write(uint8_t pin, uint8_t value)
|
||||
{
|
||||
#if GALILEO_GEN == 1
|
||||
cy8c9540a_bit_addr_t bit_addr;
|
||||
#endif
|
||||
int cpu_pin = brd_to_cpu_pin(pin);
|
||||
#if GALILEO_GEN == 1
|
||||
if(cpu_pin == -1) {
|
||||
bit_addr = galileo_brd_to_cy8c9540a_gpio_pin(pin);
|
||||
cy8c9540a_write(bit_addr, value);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
assert(quarkX1000_gpio_write(cpu_pin, value) == 0);
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2016, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef PLATFORM_GALILEO_DRIVERS_GALILEO_GPIO_H_
|
||||
#define PLATFORM_GALILEO_DRIVERS_GALILEO_GPIO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void galileo_gpio_config(uint8_t pin, int flags);
|
||||
void galileo_gpio_read(uint8_t pin, uint8_t *value);
|
||||
void galileo_gpio_write(uint8_t pin, uint8_t value);
|
||||
|
||||
#endif /* PLATFORM_GALILEO_DRIVERS_GALILEO_GPIO_H_ */
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_GALILEO_PINMUX_H_
|
||||
#define CPU_X86_DRIVERS_GALILEO_PINMUX_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum galileo_pin_group {
|
||||
GALILEO_PIN_GRP_ANALOG,
|
||||
GALILEO_PIN_GRP_DIGITAL
|
||||
} galileo_pin_group_t;
|
||||
|
||||
#define GALILEO_NUM_ANALOG_PINS 6
|
||||
#define GALILEO_NUM_DIGITAL_PINS 14
|
||||
#define GALILEO_NUM_PINS (GALILEO_NUM_ANALOG_PINS + GALILEO_NUM_DIGITAL_PINS)
|
||||
|
||||
int galileo_pinmux_initialize(void);
|
||||
|
||||
/**
|
||||
* \brief Set the indicated pin to be a digital input.
|
||||
* \param grp Indicates whether the pin is in the analog or digital group.
|
||||
* \param pin Index of pin within group.
|
||||
*/
|
||||
void galileo_pinmux_select_din(galileo_pin_group_t grp, unsigned pin);
|
||||
/**
|
||||
* \brief Set the indicated pin to be a digital output.
|
||||
*/
|
||||
void galileo_pinmux_select_dout(galileo_pin_group_t grp, unsigned pin);
|
||||
/**
|
||||
* \brief Set the indicated pin to be a PWM pin. Only a subset of the pins
|
||||
* support PWM output. This implicitly operates on the digital pin
|
||||
* group.
|
||||
*/
|
||||
void galileo_pinmux_select_pwm(unsigned pin);
|
||||
/**
|
||||
* \brief Connect the indicated pin to a serial port. This implicitly operates
|
||||
* on the digital pin group. Galileo Gen. 2 supports UART0 on pins 0 and
|
||||
* 1 and UART1 on pins 2 and 3.
|
||||
*/
|
||||
void galileo_pinmux_select_serial(unsigned pin);
|
||||
/**
|
||||
* \brief Connect analog pins 4 (SDA) and 5 (SCL) to I2C.
|
||||
*/
|
||||
void galileo_pinmux_select_i2c(void);
|
||||
/**
|
||||
* \brief Connect digital pins 11 (MOSI), 12 (MISO), and 13 (CLK) to SPI.
|
||||
*/
|
||||
void galileo_pinmux_select_spi(void);
|
||||
/**
|
||||
* \brief Set the indicated pin to be an ADC input. This implicitly operates
|
||||
* on the analog pin group.
|
||||
*/
|
||||
void galileo_pinmux_select_analog(unsigned pin);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_GALILEO_PINMUX_H_ */
|
|
@ -1,357 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "contiki.h"
|
||||
#include "gpio.h"
|
||||
#include "gpio-pcal9535a.h"
|
||||
#include "i2c.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#define REG_INPUT_PORT0 0x00
|
||||
#define REG_INPUT_PORT1 0x01
|
||||
#define REG_OUTPUT_PORT0 0x02
|
||||
#define REG_OUTPUT_PORT1 0x03
|
||||
#define REG_POL_INV_PORT0 0x04
|
||||
#define REG_POL_INV_PORT1 0x05
|
||||
#define REG_CONF_PORT0 0x06
|
||||
#define REG_CONG_PORT1 0x07
|
||||
#define REG_OUT_DRV_STRENGTH_PORT0_L 0x40
|
||||
#define REG_OUT_DRV_STRENGTH_PORT0_H 0x41
|
||||
#define REG_OUT_DRV_STRENGTH_PORT1_L 0x42
|
||||
#define REG_OUT_DRV_STRENGTH_PORT1_H 0x43
|
||||
#define REG_INPUT_LATCH_PORT0 0x44
|
||||
#define REG_INPUT_LATCH_PORT1 0x45
|
||||
#define REG_PUD_EN_PORT0 0x46
|
||||
#define REG_PUD_EN_PORT1 0x47
|
||||
#define REG_PUD_SEL_PORT0 0x48
|
||||
#define REG_PUD_SEL_PORT1 0x49
|
||||
#define REG_INT_MASK_PORT0 0x4A
|
||||
#define REG_INT_MASK_PORT1 0x4B
|
||||
#define REG_INT_STATUS_PORT0 0x4C
|
||||
#define REG_INT_STATUS_PORT1 0x4D
|
||||
#define REG_OUTPUT_PORT_CONF 0x4F
|
||||
|
||||
#define READ_PORT_TIMEOUT (CLOCK_SECOND / 100)
|
||||
#define READ_PORT_TRIES 5
|
||||
|
||||
static int
|
||||
read_port_regs(struct gpio_pcal9535a_data *data, uint8_t reg, union gpio_pcal9535a_port_data *buf)
|
||||
{
|
||||
int r;
|
||||
uint8_t tries = READ_PORT_TRIES;
|
||||
|
||||
buf->byte[0] = reg;
|
||||
buf->byte[1] = 0;
|
||||
|
||||
if(quarkX1000_i2c_write(buf->byte, 1, data->i2c_slave_addr) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
clock_wait(READ_PORT_TIMEOUT);
|
||||
|
||||
r = quarkX1000_i2c_read(buf->byte, 2, data->i2c_slave_addr);
|
||||
if(r == 0) {
|
||||
break;
|
||||
}
|
||||
} while(tries--);
|
||||
|
||||
if(r < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
write_port_regs(struct gpio_pcal9535a_data *data, uint8_t reg, union gpio_pcal9535a_port_data *buf)
|
||||
{
|
||||
uint8_t cmd[] = { reg, buf->byte[0], buf->byte[1] };
|
||||
|
||||
if(quarkX1000_i2c_polling_write(cmd, sizeof(cmd), data->i2c_slave_addr) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
setup_pin_dir(struct gpio_pcal9535a_data *data, uint32_t pin, int flags)
|
||||
{
|
||||
union gpio_pcal9535a_port_data *port = &data->reg_cache.dir;
|
||||
uint16_t bit_mask, new_value = 0;
|
||||
|
||||
bit_mask = 1 << pin;
|
||||
|
||||
if((flags & QUARKX1000_GPIO_DIR_MASK) == QUARKX1000_GPIO_IN) {
|
||||
new_value = 1 << pin;
|
||||
}
|
||||
|
||||
port->all &= ~bit_mask;
|
||||
port->all |= new_value;
|
||||
|
||||
return write_port_regs(data, REG_CONF_PORT0, port);
|
||||
}
|
||||
static int
|
||||
setup_pin_pullupdown(struct gpio_pcal9535a_data *data, uint32_t pin, int flags)
|
||||
{
|
||||
union gpio_pcal9535a_port_data *port;
|
||||
uint16_t bit_mask, new_value = 0;
|
||||
|
||||
if((flags & QUARKX1000_GPIO_PUD_MASK) != QUARKX1000_GPIO_PUD_NORMAL) {
|
||||
port = &data->reg_cache.pud_sel;
|
||||
bit_mask = 1 << pin;
|
||||
|
||||
if((flags & QUARKX1000_GPIO_PUD_MASK) == QUARKX1000_GPIO_PUD_PULL_UP) {
|
||||
new_value = 1 << pin;
|
||||
}
|
||||
|
||||
port->all &= ~bit_mask;
|
||||
port->all |= new_value;
|
||||
|
||||
if(write_port_regs(data, REG_PUD_SEL_PORT0, port) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
port = &data->reg_cache.pud_en;
|
||||
bit_mask = 1 << pin;
|
||||
|
||||
if((flags & QUARKX1000_GPIO_PUD_MASK) != QUARKX1000_GPIO_PUD_NORMAL) {
|
||||
new_value = 1 << pin;
|
||||
}
|
||||
|
||||
port->all &= ~bit_mask;
|
||||
port->all |= new_value;
|
||||
|
||||
return write_port_regs(data, REG_PUD_EN_PORT0, port);
|
||||
}
|
||||
static int
|
||||
setup_pin_polarity(struct gpio_pcal9535a_data *data, uint32_t pin, int flags)
|
||||
{
|
||||
union gpio_pcal9535a_port_data *port = &data->reg_cache.pol_inv;
|
||||
uint16_t bit_mask, new_value = 0;
|
||||
|
||||
bit_mask = 1 << pin;
|
||||
|
||||
if((flags & QUARKX1000_GPIO_POL_MASK) == QUARKX1000_GPIO_POL_INV) {
|
||||
new_value = 1 << pin;
|
||||
}
|
||||
|
||||
port->all &= ~bit_mask;
|
||||
port->all |= new_value;
|
||||
|
||||
if(write_port_regs(data, REG_POL_INV_PORT0, port) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->out_pol_inv = port->all;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
gpio_pcal9535a_write(struct gpio_pcal9535a_data *data, uint32_t pin, uint32_t value)
|
||||
{
|
||||
union gpio_pcal9535a_port_data *port = &data->reg_cache.output;
|
||||
uint16_t bit_mask, new_value;
|
||||
|
||||
if(!quarkX1000_i2c_is_available()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bit_mask = 1 << pin;
|
||||
|
||||
new_value = (value << pin) & bit_mask;
|
||||
new_value ^= (data->out_pol_inv & bit_mask);
|
||||
new_value &= bit_mask;
|
||||
|
||||
port->all &= ~bit_mask;
|
||||
port->all |= new_value;
|
||||
|
||||
return write_port_regs(data, REG_OUTPUT_PORT0, port);
|
||||
}
|
||||
int
|
||||
gpio_pcal9535a_read(struct gpio_pcal9535a_data *data, uint32_t pin, uint32_t *value)
|
||||
{
|
||||
union gpio_pcal9535a_port_data buf;
|
||||
|
||||
if(!quarkX1000_i2c_is_available()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(read_port_regs(data, REG_INPUT_PORT0, &buf) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*value = (buf.all >> pin) & 0x01;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
gpio_pcal9535a_config(struct gpio_pcal9535a_data *data, uint32_t pin, int flags)
|
||||
{
|
||||
if(!quarkX1000_i2c_is_available()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(setup_pin_dir(data, pin, flags) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(setup_pin_polarity(data, pin, flags) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(setup_pin_pullupdown(data, pin, flags) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int
|
||||
setup_port_dir(struct gpio_pcal9535a_data *data, uint32_t pin, int flags)
|
||||
{
|
||||
union gpio_pcal9535a_port_data *port = &data->reg_cache.dir;
|
||||
|
||||
port->all = ((flags & QUARKX1000_GPIO_DIR_MASK) == QUARKX1000_GPIO_IN) ? 0xFFFF : 0x0;
|
||||
|
||||
return write_port_regs(data, REG_CONF_PORT0, port);
|
||||
}
|
||||
static int
|
||||
setup_port_pullupdown(struct gpio_pcal9535a_data *data, uint32_t pin, int flags)
|
||||
{
|
||||
union gpio_pcal9535a_port_data *port;
|
||||
|
||||
if((flags & QUARKX1000_GPIO_PUD_MASK) != QUARKX1000_GPIO_PUD_NORMAL) {
|
||||
port = &data->reg_cache.pud_sel;
|
||||
port->all = ((flags & QUARKX1000_GPIO_PUD_MASK) == QUARKX1000_GPIO_PUD_PULL_UP) ? 0xFFFF : 0x0;
|
||||
|
||||
if(write_port_regs(data, REG_PUD_SEL_PORT0, port) < 0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
port = &data->reg_cache.pud_en;
|
||||
port->all = ((flags & QUARKX1000_GPIO_PUD_MASK) != QUARKX1000_GPIO_PUD_NORMAL) ? 0xFFFF : 0x0;
|
||||
|
||||
return write_port_regs(data, REG_PUD_EN_PORT0, port);
|
||||
}
|
||||
static int
|
||||
setup_port_polarity(struct gpio_pcal9535a_data *data, uint32_t pin, int flags)
|
||||
{
|
||||
union gpio_pcal9535a_port_data *port = &data->reg_cache.pol_inv;
|
||||
|
||||
port->all = ((flags & QUARKX1000_GPIO_POL_MASK) == QUARKX1000_GPIO_POL_INV) ? 0xFFFF : 0x0;
|
||||
|
||||
if(write_port_regs(data, REG_POL_INV_PORT0, port) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->out_pol_inv = port->all;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
gpio_pcal9535a_write_port(struct gpio_pcal9535a_data *data, uint32_t pin, uint32_t value)
|
||||
{
|
||||
union gpio_pcal9535a_port_data *port = &data->reg_cache.output;
|
||||
uint16_t bit_mask, new_value;
|
||||
|
||||
if(!quarkX1000_i2c_is_available()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
port->all = value;
|
||||
bit_mask = data->out_pol_inv;
|
||||
|
||||
new_value = value & bit_mask;
|
||||
new_value ^= data->out_pol_inv;
|
||||
new_value &= bit_mask;
|
||||
|
||||
port->all &= ~bit_mask;
|
||||
port->all |= new_value;
|
||||
|
||||
return write_port_regs(data, REG_OUTPUT_PORT0, port);
|
||||
}
|
||||
int
|
||||
gpio_pcal9535a_read_port(struct gpio_pcal9535a_data *data, uint32_t pin, uint32_t *value)
|
||||
{
|
||||
union gpio_pcal9535a_port_data buf;
|
||||
|
||||
if(!quarkX1000_i2c_is_available()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(read_port_regs(data, REG_INPUT_PORT0, &buf) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*value = buf.all;
|
||||
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
gpio_pcal9535a_config_port(struct gpio_pcal9535a_data *data, uint32_t pin, int flags)
|
||||
{
|
||||
if(!quarkX1000_i2c_is_available()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(setup_port_dir(data, pin, flags) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(setup_port_polarity(data, pin, flags) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(setup_port_pullupdown(data, pin, flags) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int
|
||||
gpio_pcal9535a_init(struct gpio_pcal9535a_data *data, uint16_t i2c_slave_addr)
|
||||
{
|
||||
/* has to init after I2C master */
|
||||
if(!quarkX1000_i2c_is_available()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
data->i2c_slave_addr = i2c_slave_addr;
|
||||
|
||||
/* default for registers according to datasheet */
|
||||
data->reg_cache.output.all = 0xFFFF;
|
||||
data->reg_cache.pol_inv.all = 0x0;
|
||||
data->reg_cache.dir.all = 0xFFFF;
|
||||
data->reg_cache.pud_en.all = 0x0;
|
||||
data->reg_cache.pud_sel.all = 0xFFFF;
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015, Intel Corporation. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of the copyright holder nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef CPU_X86_DRIVERS_GPIO_PCAL9535A_H_
|
||||
#define CPU_X86_DRIVERS_GPIO_PCAL9535A_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
union gpio_pcal9535a_port_data {
|
||||
uint16_t all;
|
||||
uint8_t port[2];
|
||||
uint8_t byte[2];
|
||||
};
|
||||
|
||||
struct gpio_pcal9535a_data {
|
||||
uint16_t i2c_slave_addr;
|
||||
uint32_t out_pol_inv;
|
||||
|
||||
struct {
|
||||
union gpio_pcal9535a_port_data output;
|
||||
union gpio_pcal9535a_port_data pol_inv;
|
||||
union gpio_pcal9535a_port_data dir;
|
||||
union gpio_pcal9535a_port_data pud_en;
|
||||
union gpio_pcal9535a_port_data pud_sel;
|
||||
} reg_cache;
|
||||
};
|
||||
|
||||
int gpio_pcal9535a_init(struct gpio_pcal9535a_data *data, uint16_t i2c_slave_addr);
|
||||
|
||||
int gpio_pcal9535a_config(struct gpio_pcal9535a_data *data, uint32_t pin, int flags);
|
||||
int gpio_pcal9535a_read(struct gpio_pcal9535a_data *data, uint32_t pin, uint32_t *value);
|
||||
int gpio_pcal9535a_write(struct gpio_pcal9535a_data *data, uint32_t pin, uint32_t value);
|
||||
|
||||
int gpio_pcal9535a_config_port(struct gpio_pcal9535a_data *data, uint32_t pin, int flags);
|
||||
int gpio_pcal9535a_read_port(struct gpio_pcal9535a_data *data, uint32_t pin, uint32_t *value);
|
||||
int gpio_pcal9535a_write_port(struct gpio_pcal9535a_data *data, uint32_t pin, uint32_t value);
|
||||
|
||||
#endif /* CPU_X86_DRIVERS_GPIO_PCAL9535A_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue