Merge branch zcu102-7.0.0 into master

This commit is contained in:
Adrian Danis 2017-10-03 12:16:08 +11:00
commit 383a6d959f
32 changed files with 673 additions and 243 deletions

View file

@ -10,3 +10,4 @@ manual/figs/*
.git/*
*parsetab.py
manual/*
CHANGES

33
CHANGES Normal file
View file

@ -0,0 +1,33 @@
Revision history for seL4
For more information see the release notes at https://wiki.sel4.systems/ReleaseNotes
---
7.0.0-dev
= Changes =
= Upgrade notes =
---
7.0.0 2017-09-05
= Changes =
* Support for building standalone ia32 kernel added
* ia32: Set sensible defaults for FS and GS selectors
* aarch64: Use tpidrro_el0 for IPC buffer instead of tpidr_el0
* More seL4 manual documentation added for aarch64 object invocations
* Default NUM_DOMAINS set to 16 for x86-64 standalone builds
* libsel4: Return seL4_Error in invocation stubs in 8fb06eecff9 ''' This is a source code level breaking change '''
* Add a CMake based build system
* x86: Increase TCB size for debug builds
* libsel4: x86: Remove nested struct declarations ''' This is a source code level breaking change '''
* Bugfix: x86: Unmap pages when delete non final frame caps
= Upgrade notes =
* This release is not source compatible with previous releases.
* seL4 invocations that previously returned long now return seL4_Error which is an enum. Our libraries have already been updated to reflect this change, but in other places where seL4 invocations are used directly, the return types will need to be updated to reflect this change.
* On x86 some structs in the Bootinfo have been rearranged. This only affects seL4_VBEModeInfoBlock_t which is used if VESA BIOS Extensions (VBE) information is being used.
= Known issues =
* One of our tests is non-deterministicly becoming unresponsive on the SMP release build on the Sabre IMX.6 platform, which is a non verified configuration of the kernel. We are working on fixing this problem, and will likely do a point release once it is fixed.

View file

@ -11,6 +11,7 @@
#
cmake_minimum_required(VERSION 3.7.2)
include(CheckCSourceCompiles)
project(seL4 C ASM)
# First find our helpers
@ -59,8 +60,21 @@ if(KernelArchX86)
endif()
endif()
if(KernelArchARM)
set(c_common_flags "${c_common_flags} -mcpu=${KernelArmCPU} -march=${KernelArmArmV}${KernelArmMachFeatureModifiers}")
set(asm_common_flags "${asm_common_flags} -Wa,-mcpu=${KernelArmCPU} -Wa,-march=${KernelArmArmV}${KernelArmMachFeatureModifiers}")
set(c_common_flags "${c_common_flags} -mcpu=${KernelArmCPU}")
set(asm_common_flags "${asm_common_flags} -Wa,-mcpu=${KernelArmCPU}")
# See if the current compiler understands the chosen -mcpu and -march flags when used together.
# them not being supported unfortunately does not indicate an error as older versions of gcc
# *require* mcpu and march flags that are considered invalid on newer versions of gcc. Overall
# newer versions of gcc recommend just setting 'mcpu' and letting the internals determine the
# approproate march and mtune settings, as such we have already set the desired mcpu and
# we will just add the march for safety for the older compilers if it does not cause conflicts
set(CMAKE_REQUIRED_FLAGS "${c_common_flags} -march=${KernelArmArmV}${KernelArmMachFeatureModifiers}")
set(CMAKE_REQUIRED_DEFINITIONS "")
check_c_source_compiles("void main(void){}" ARM_MCPU_MARCH_VALID FAIL_REGEX "warning|error")
if (ARM_MCPU_MARCH_VALID)
set(c_common_flags "${c_common_flags} -march=${KernelArmArmV}${KernelArmMachFeatureModifiers}")
set(asm_common_flags "${asm_common_flags} -Wa,-march=${KernelArmArmV}${KernelArmMachFeatureModifiers}")
endif()
endif()
set(common_flags "${common_flags} ${build_arch}")
if(Kernel64)

View file

@ -357,6 +357,12 @@ menu "seL4 System Parameters"
the kernel checks for pending interrupts (and preempts the
currently running syscall if interrupts are pending).
config RESET_CHUNK_BITS
int "Max chunks to reset when clearing memory"
default 8
help
Maximum size in bits of chunks of memory to zero before checking a preemption point.
config MAX_NUM_BOOTINFO_UNTYPED_CAPS
int "Max number of bootinfo untyped caps"
default 167

View file

@ -1 +1 @@
7.0.0
7.0.0-dev

View file

@ -18,10 +18,10 @@ set(configure_string "")
config_set(KernelIsMaster KERNEL_MASTER ON)
# Proof based configuration variables
find_path(CSPEC_DIR KernelState_C.thy CMAKE_FIND_ROOT_PATH_BOTH)
set(SKIP_MODIFIES ON CACHE INTERNAL "")
set(TOPLEVELTYPES "cte_C;tcb_C;endpoint_C;notification_C;asid_pool_C;pte_C;pde_C;user_data_C;user_data_device_C" CACHE INTERNAL "")
set(SORRY_BITFIELD_PROOFS OFF CACHE INTERNAL "")
set(CSPEC_DIR "." CACHE PATH "")
set(SKIP_MODIFIES ON CACHE BOOL "")
set(TOPLEVELTYPES "cte_C;tcb_C;endpoint_C;notification_C;asid_pool_C;pte_C;pde_C;user_data_C;user_data_device_C" CACHE STRING "")
set(SORRY_BITFIELD_PROOFS OFF CACHE BOOL "")
find_file(UMM_TYPES umm_types.txt CMAKE_FIND_ROOT_PATH_BOTH)
set(force FORCE)
if(KernelVerificationBuild)
@ -83,6 +83,11 @@ config_string(KernelMaxNumWorkUnitsPerPreemption MAX_NUM_WORK_UNITS_PER_PREEMPTI
DEFAULT 100
UNQUOTE
)
config_string(KernelResetChunkBits RESET_CHUNK_BITS
"Maximum size in bits of chunks of memory to zero before checking a preemption point."
DEFAULT 8
UNQUOTE
)
config_string(KernelMaxNumBootinfoUntypedCaps MAX_NUM_BOOTINFO_UNTYPED_CAPS
"Max number of bootinfo untyped caps"
DEFAULT 230

View file

@ -0,0 +1,29 @@
#
# Copyright 2017, Data61
# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
# ABN 41 687 119 230.
#
# This software may be distributed and modified according to the terms of
# the GNU General Public License version 2. Note that NO WARRANTY is provided.
# See "LICENSE_GPLv2.txt" for details.
#
# @TAG(DATA61_GPL)
#
set(KernelARMPlatform "jetson" CACHE STRING "")
set(KernelArch "arm" CACHE STRING "")
set(KernelArmSel4Arch "arm_hyp" CACHE STRING "")
set(KernelArmHypervisorSupport ON CACHE BOOL "")
set(KernelVerificationBuild ON CACHE BOOL "")
set(KernelIPCBufferLocation "threadID_register" CACHE STRING "")
set(KernelMaxNumNodes "1" CACHE STRING "")
set(KernelOptimisation "-O2" CACHE STRING "")
set(KernelRetypeFanOutLimit "256" CACHE STRING "")
set(KernelBenchmarks "none" CACHE STRING "")
set(KernelDangerousCodeInjection OFF CACHE BOOL "")
set(KernelFastpath ON CACHE BOOL "")
set(KernelPrinting OFF CACHE BOOL "")
set(KernelNumDomains 16 CACHE STRING "")
set(KernelMaxNumBootinfoUntypedCap 166 CACHE STRING "")
set(KernelRootCNodeSizeBits 19 CACHE STRING "")
set(KernelMaxNumBootinfoUntypedCaps 50 CACHE STRING "")

View file

@ -0,0 +1,26 @@
#
# Copyright 2017, Data61
# Commonwealth Scientific and Industrial Research Organisation (CSIRO)
# ABN 41 687 119 230.
#
# This software may be distributed and modified according to the terms of
# the GNU General Public License version 2. Note that NO WARRANTY is provided.
# See "LICENSE_GPLv2.txt" for details.
#
# @TAG(DATA61_GPL)
#
set(KernelArch "x86" CACHE STRING "")
set(KernelX86Sel4Arch "x86_64" CACHE STRING "")
set(KernelVerificationBuild ON CACHE BOOL "")
set(KernelMaxNumNodes "1" CACHE STRING "")
set(KernelOptimisation "-O2" CACHE STRING "")
set(KernelRetypeFanOutLimit "256" CACHE STRING "")
set(KernelBenchmarks "none" CACHE STRING "")
set(KernelDangerousCodeInjection OFF CACHE BOOL "")
set(KernelFastpath ON CACHE BOOL "")
set(KernelPrinting OFF CACHE BOOL "")
set(KernelNumDomains 16 CACHE STRING "")
set(KernelMaxNumBootinfoUntypedCap 166 CACHE STRING "")
set(KernelRootCNodeSizeBits 19 CACHE STRING "")
set(KernelMaxNumBootinfoUntypedCaps 50 CACHE STRING "")

View file

@ -150,7 +150,6 @@
#define CONFIG_LIB_SEL4_INLINE_INVOCATIONS 1
#define CONFIG_LIB_SEL4_MUSLC_SYS 1
#define CONFIG_HAVE_LIB_SEL4_TEST 1
#define CONFIG_IOMMU 1
#define CONFIG_LIB_MUSL_C 1
#define CONFIG_MAX_NUM_WORK_UNITS_PER_PREEMPTION 100
#define CONFIG_USER_CFLAGS ""

View file

@ -407,7 +407,7 @@ block tss {
-- PDs and PTs
block pde_small {
block pde_pt {
field_high pt_base_address 20
field avl 3
padding 1
@ -438,7 +438,7 @@ block pde_large {
}
tagged_union pde page_size {
tag pde_small 0
tag pde_pt 0
tag pde_large 1
}
@ -491,7 +491,7 @@ block ept_pde_2m {
field read 1
}
block ept_pde_4k {
block ept_pde_pt {
padding 32
field_high pt_base_address 20
field avl_cte_depth 3
@ -504,7 +504,7 @@ block ept_pde_4k {
}
tagged_union ept_pde page_size {
tag ept_pde_4k 0
tag ept_pde_pt 0
tag ept_pde_2m 1
}

View file

@ -532,7 +532,7 @@ block pde_large {
field present 1
}
block pde_small {
block pde_pt {
field xd 1
padding 11
padding 1
@ -549,7 +549,7 @@ block pde_small {
}
tagged_union pde page_size {
tag pde_small 0
tag pde_pt 0
tag pde_large 1
}
@ -605,7 +605,7 @@ block ept_pde_2m {
field read 1
}
block ept_pde_4k {
block ept_pde_pt {
padding 13
field_high pt_base_address 39
field avl_cte_depth 3
@ -618,7 +618,7 @@ block ept_pde_4k {
}
tagged_union ept_pde page_size {
tag ept_pde_4k 0
tag ept_pde_pt 0
tag ept_pde_2m 1
}

View file

@ -148,7 +148,7 @@ enum vm_rights {
VMReadOnly = 2,
VMReadWrite = 3
};
typedef uint32_t vm_rights_t;
typedef word_t vm_rights_t;
#include <mode/object/structures.h>

View file

@ -47,8 +47,7 @@ typedef enum _interrupt_t {
int_max = 255
} interrupt_t;
typedef enum _irq_t {
irqInvalid = -1,
typedef enum _platform_irq_t {
irq_isa_min = int_irq_isa_min - IRQ_INT_OFFSET,
irq_isa_max = int_irq_isa_max - IRQ_INT_OFFSET,
irq_user_min = int_irq_user_min - IRQ_INT_OFFSET,
@ -61,8 +60,14 @@ typedef enum _irq_t {
irq_remote_call_ipi = int_remote_call_ipi - IRQ_INT_OFFSET,
irq_reschedule_ipi = int_reschedule_ipi - IRQ_INT_OFFSET,
#endif
maxIRQ = int_irq_max - IRQ_INT_OFFSET
} irq_t;
maxIRQ = int_irq_max - IRQ_INT_OFFSET,
/* This is explicitly 255, instead of -1 like on some other platforms, to ensure
* that comparisons between an irq_t (a uint8_t) and irqInvalid (some kind of signed int)
* are well defined and behave as expected */
irqInvalid = 255,
} platform_irq_t;
typedef uint8_t irq_t;
#define IRQ_CNODE_BITS 13

View file

@ -239,7 +239,7 @@
</interface>
<interface name="seL4_X86_ASIDPool" manual_name="ASID Pool">
<method id="X86ASIDPoolAssign" name="Assign" manual_label='asid_pool_assign'>
<method id="X86ASIDPoolAssign" name="Assign" manual_label='asidpool_assign'>
<brief>
Assign an ASID pool.
</brief>
@ -368,61 +368,206 @@
</method>
</interface>
<interface name="seL4_TCB" manual_name="TCB">
<method id="TCBSetEPTRoot" name="SetEPTRoot" condition="defined(CONFIG_VTX)" manual_name="Set EPT Root">
<param dir="in" name="vcpu" type="seL4_CPtr"/>
<method id="TCBSetEPTRoot" name="SetEPTRoot" condition="defined(CONFIG_VTX)" manual_name="Set EPT Root" manual_label="set_eptroot">
<brief>
Set the EPT root of a thread
</brief>
<description>
See <autoref label='sec:virt'/>.
</description>
<param dir="in" name="eptpml4" type="seL4_CPtr"
description='CPTR to an EPT PML4 object to act as the guest mode vspace root'/>
</method>
</interface>
<interface name="seL4_X86_VCPU" manual_name="VCPU">
<interface name="seL4_X86_VCPU" manual_name="VCPU" cap_description='VCPU object to operate on'>
<method id="X86VCPUSetTCB" name="SetTCB" condition="defined(CONFIG_VTX)" manual_name="Set TCB">
<param dir="in" name="tcb" type="seL4_CNode" />
<brief>
Bind TCB to VCPU
</brief>
<description>
Configures the one-to-one binding of a VCPU and TCB, overwriting any previous binding
in both. See <autoref label='sec:virt'/>.
</description>
<param dir="in" name="tcb" type="seL4_CNode" description='CPTR of the TCB to bind to'/>
</method>
<method id="X86VCPUReadVMCS" name="ReadVMCS" condition="defined(CONFIG_VTX)" manual_name="Read VMCS">
<param dir="in" name="field" type="seL4_Word"/>
<param dir="out" name="value" type="seL4_Word"/>
<method id="X86VCPUReadVMCS" name="ReadVMCS" condition="defined(CONFIG_VTX)" manual_name="Read VMCS" manual_label="vcpu_readvmcs">
<brief>
Read VMCS field from the hardware
</brief>
<description>
Thin wrapper around the <texttt text='vmread'/> instruction that is performed on the
VMCS region that is part of the VCPU object. After validating that a legal
field is requested the value of `vmread` is returned directly in the result.
</description>
<return>
A <texttt text='seL4_X86_VCPU_ReadVMCS_t'/> struct that contains a
<texttt text='seL4_Word value'/>, which holds the return result of the <texttt text='vmread'/> instruction,
and <texttt text='int error'/>. See <autoref label='sec:errors'/> for a description
of the message register and tag contents upon error.
</return>
<param dir="in" name="field" type="seL4_Word"
description='Field to give to \texttt{vmread} instruction'/>
<param dir="out" name="value" type="seL4_Word"
description='Value returned by `vmread` instruction'/>
</method>
<method id="X86VCPUWriteVMCS" name="WriteVMCS" condition="defined(CONFIG_VTX)" manual_name="Write VMCS">
<param dir="in" name="field" type="seL4_Word"/>
<param dir="in" name="value" type="seL4_Word"/>
<param dir="out" name="written" type="seL4_Word"/>
<method id="X86VCPUWriteVMCS" name="WriteVMCS" condition="defined(CONFIG_VTX)" manual_name="Write VMCS" manual_label="vcpu_writevmcs">
<brief>
Write VMCS field to the hardware
</brief>
<description>
Thin wrapper around the `vmwrite` instruction that is performed on the
VMCS region that is part of the VCPU object. As well as validating that
a legal field is requested, the value may be modified to ensure any
bits that are fixed in the hardware are correct, and that any features
required for kernel correctness are not disabled (see <autoref label='sec:virt'/>).
The final value written to the hardware is returned and can be compared
to the input parameter to determine what bits the kernel changed.
</description>
<return>
A <texttt text='seL4_X86_VCPU_WriteVMCS_t'/> struct that contains a
<texttt text='seL4_Word writen'/>, which holds the final value written with the <texttt text='vmwrite'/> instruction,
and <texttt text='int error'/>. See <autoref label='sec:errors'/> for a description
of the message register and tag contents upon error.
</return>
<param dir="in" name="field" type="seL4_Word"
description='Field to give to `vmwrite` instruction'/>
<param dir="in" name="value" type="seL4_Word"
description='Value to write using `vmwrite` instruction'/>
<param dir="out" name="written" type="seL4_Word"
description='Final value written using `vmwrite` after kernel validation'/>
</method>
<method id="X86VCPUEnableIOPort" name="EnableIOPort" condition="defined(CONFIG_VTX)"
manual_name="Enable IO Port">
<param dir="in" name="ioPort" type="seL4_CNode"/>
<param dir="in" name="low" type="seL4_Word"/>
<param dir="in" name="high" type="seL4_Word"/>
manual_name="Enable IO Port" manual_label="vcpu_enableioport">
<brief>
Enable I/O port range in guest execution
</brief>
<description>
Enables a range of I/O ports for direct access by the execution mode in
the <texttt text='VCPU'/>. The requested port range must be a sub range
of the provided I/O port capability.
This also establishes a link between the provided I/O port capability and
the <texttt text='VCPU'/>, see <autoref label='sec:virt'/> for details.
</description>
<param dir="in" name="ioPort" type="seL4_CPtr"
description='I/O port capability whose authority is being delegating'/>
<param dir="in" name="low" type="seL4_Word"
description='Start of the I/O port range to enable'/>
<param dir="in" name="high" type="seL4_Word"
description='Last I/O port in the range to enable'/>
</method>
<method id="X86VCPUDisableIOPort" name="DisableIOPort" condition="defined(CONFIG_VTX)"
manual_name="Disable IO Port">
<param dir="in" name="low" type="seL4_Word"/>
<param dir="in" name="high" type="seL4_Word"/>
<brief>
Disable I/O port range in privileged execution
</brief>
<description>
Disable a range of I/O ports for direct access by the execution mode in
the <texttt text='VCPU'/>.
</description>
<param dir="in" name="low" type="seL4_Word"
description='Start of the I/O port range to disable'/>
<param dir="in" name="high" type="seL4_Word"
description='Last I/O port in the range to disable'/>
</method>
<method id="X86VCPUWriteRegisters" name="WriteRegisters" condition="defined(CONFIG_VTX)"
manual_name="Write Registers">
<param dir="in" name="regs" type="seL4_VCPUContext"/>
<brief>
Set guest mode registers to the fields of a given <texttt text="seL4_VCPUContext"/>
</brief>
<description>
Sets the guest mode registers, which is any registers not already part of the VMCS.
</description>
<param dir="in" name="regs" type="seL4_VCPUContext"
description='Data structure containing the new register values.'/>
</method>
</interface>
<interface name="seL4_X86_EPTPDPT" manual_name="Extended Page Table Page Directory Page Table">
<interface name="seL4_X86_EPTPDPT" manual_name="Extended Page Table Page Directory Page Table"
cap_description="Capability to the EPT PDPT being operated on.">
<method id="X86EPTPDPTMap" name="Map" condition="defined(CONFIG_VTX)">
<param dir="in" name="pml4" type="seL4_X86_EPTPML4"/>
<param dir="in" name="gpa" type="seL4_Word"/>
<param dir="in" name="attr" type="seL4_X86_VMAttributes"/>
<brief>
Map an EPT page directory page table.
</brief>
<description>
See <autoref label="ch:vspace"/>
</description>
<param dir="in" name="pml4" type="seL4_X86_EPTPML4"
description='Capability to the EPT root which will contain the mapping'/>
<param dir="in" name="gpa" type="seL4_Word"
description='Guest physical address to map the page into.'/>
<param dir="in" name="attr" type="seL4_X86_VMAttributes">
<description>
VM attributes for the mapping. Possible values for this type are
given in <autoref label='ch:vspace'/>
</description>
</param>
</method>
<method id="X86EPTPDPTUnmap" name="Unmap" condition="defined(CONFIG_VTX)">
<brief>
Unmap an EPT page directory page table.
</brief>
<description>
See <autoref label="ch:vspace"/>
</description>
</method>
<method id="X86EPTPDPTUnmap" name="Unmap" condition="defined(CONFIG_VTX)"/>
</interface>
<interface name="seL4_X86_EPTPD" manual_name="Extended Page Table Page Directory">
<interface name="seL4_X86_EPTPD" manual_name="Extended Page Table Page Directory"
cap_description="Capability to the EPT PD being operated on.">
<method id="X86EPTPDMap" name="Map" condition="defined(CONFIG_VTX)">
<param dir="in" name="pml4" type="seL4_X86_EPTPML4"/>
<param dir="in" name="gpa" type="seL4_Word"/>
<param dir="in" name="attr" type="seL4_X86_VMAttributes"/>
<brief>
Map an EPT page directory.
</brief>
<description>
See <autoref label="ch:vspace"/>
</description>
<param dir="in" name="pml4" type="seL4_X86_EPTPML4"
description='Capability to the EPT root which will contain the mapping'/>
<param dir="in" name="gpa" type="seL4_Word"
description='Guest physical address to map the page into.'/>
<param dir="in" name="attr" type="seL4_X86_VMAttributes">
<description>
VM attributes for the mapping. Possible values for this type are
given in <autoref label='ch:vspace'/>
</description>
</param>
</method>
<method id="X86EPTPDUnmap" name="Unmap" condition="defined(CONFIG_VTX)">
<brief>
Unmap an EPT page directory.
</brief>
<description>
See <autoref label="ch:vspace"/>
</description>
</method>
<method id="X86EPTPDUnmap" name="Unmap" condition="defined(CONFIG_VTX)"/>
</interface>
<interface name="seL4_X86_EPTPT" manual_name="Extended Page Table Page Table">
<interface name="seL4_X86_EPTPT" manual_name="Extended Page Table Page Table"
cap_description="Capability to the EPT PT being operated on.">
<method id="X86EPTPTMap" name="Map" condition="defined(CONFIG_VTX)">
<param dir="in" name="pml4" type="seL4_X86_EPTPML4"/>
<param dir="in" name="gpa" type="seL4_Word"/>
<param dir="in" name="attr" type="seL4_X86_VMAttributes"/>
<brief>
Map an EPT page table.
</brief>
<description>
See <autoref label="ch:vspace"/>
</description>
<param dir="in" name="pml4" type="seL4_X86_EPTPML4"
description='Capability to the EPT root which will contain the mapping'/>
<param dir="in" name="gpa" type="seL4_Word"
description='Guest physical address to map the page into.'/>
<param dir="in" name="attr" type="seL4_X86_VMAttributes">
<description>
VM attributes for the mapping. Possible values for this type are
given in <autoref label='ch:vspace'/>
</description>
</param>
</method>
<method id="X86EPTPTUnmap" name="Unmap" condition="defined(CONFIG_VTX)">
<brief>
Unmap an EPT page table.
</brief>
<description>
See <autoref label="ch:vspace"/>
</description>
</method>
<method id="X86EPTPTUnmap" name="Unmap" condition="defined(CONFIG_VTX)"/>
</interface>
</api>

View file

@ -474,6 +474,67 @@ seL4_BenchmarkResetThreadUtilisation(seL4_Word tcb_cptr);
#endif
/** @} */
#ifdef CONFIG_ARCH_X86
/**
* @defgroup X86SystemCalls X86 System Calls
* @{
*/
#ifdef CONFIG_VTX
/**
* @xmlonly <manual name="VMEnter" label="sel4_vmenter"/> @endxmlonly
* @brief Change current thread to execute from its bound VCPU
*
* Changes the execution mode of the current thread from normal TCB execution, to
* guest execution using its bound VCPU.
* @xmlonly
* For details on VCPUs and execution modes see <autoref label="sec:virt"/>.
* @endxmlonly
*
* Invoking `seL4_VMEnter` is similar to replying to a fault in that updates to the registers
* can be given in the message, but unlike a fault no message info
* @xmlonly
* (see <autoref label="sec:messageinfo"/>)
* @endxmlonly
* is sent as the registers are not optional and the number that must be sent is fixed.
* The mapping of hardware register to message register is
* - `SEL4_VMENTER_CALL_EIP_MR` Address to start executing instructions at in the guest mode
* - `SEL4_VMENTER_CALL_CONTROL_PPC_MR` New value for the Primary Processor Based VM Execution Controls
* - `SEL4_VMENTER_CALL_CONTROL_ENTRY_MR` New value for the VM Entry Controls
*
* On return these same three message registers will be filled with the values at the point
* that the privlidged mode ceased executing. If this function returns with `SEL4_VMENTER_RESULT_FAULT`
* then the following additional message registers will be filled out
* - `SEL4_VMENTER_FAULT_REASON_MR`
* - `SEL4_VMENTER_FAULT_QUALIFICATION_MR`
* - `SEL4_VMENTER_FAULT_INSTRUCTION_LEN_MR`
* - `SEL4_VMENTER_FAULT_GUEST_PHYSICAL_MR`
* - `SEL4_VMENTER_FAULT_RFLAGS_MR`
* - `SEL4_VMENTER_FAULT_GUEST_INT_MR`
* - `SEL4_VMENTER_FAULT_CR3_MR`
* - `SEL4_VMENTER_FAULT_EAX`
* - `SEL4_VMENTER_FAULT_EBX`
* - `SEL4_VMENTER_FAULT_ECX`
* - `SEL4_VMENTER_FAULT_EDX`
* - `SEL4_VMENTER_FAULT_ESI`
* - `SEL4_VMENTER_FAULT_EDI`
* - `SEL4_VMENTER_FAULT_EBP`
*
* @param[out] sender The address to write sender information to.
* If the syscall returns due to receiving a notification
* on the bound notification then the sender information
* is the badge of the notification capability that was invoked.
* This parameter is ignored if `NULL`.
* @return `SEL4_VMENTER_RESULT_NOTIF` if a notification was received or `SEL4_VMENTER_RESULT_FAULT`
* if the guest mode execution faulted for any reason
*/
LIBSEL4_INLINE_FUNC seL4_Word
seL4_VMEnter(seL4_Word *sender);
#endif
/** @} */
#endif
/** @} */
#endif /* __LIBSEL4_SYSCALLS_H */

View file

@ -505,14 +505,14 @@ seL4_Yield(void)
#ifdef CONFIG_VTX
LIBSEL4_INLINE_FUNC seL4_Word
seL4_VMEnter(seL4_CPtr vcpu, seL4_Word *sender)
seL4_VMEnter(seL4_Word *sender)
{
seL4_Word fault;
seL4_Word badge;
seL4_Word mr0 = seL4_GetMR(0);
seL4_Word mr1 = seL4_GetMR(1);
x86_sys_send_recv(seL4_SysVMEnter, vcpu, &badge, 0, &fault, &mr0, &mr1);
x86_sys_send_recv(seL4_SysVMEnter, 0, &badge, 0, &fault, &mr0, &mr1);
seL4_SetMR(0, mr0);
seL4_SetMR(1, mr1);

View file

@ -304,7 +304,7 @@ seL4_Yield(void)
#ifdef CONFIG_VTX
static inline seL4_Word
seL4_VMEnter(seL4_CPtr vcpu, seL4_Word *sender)
seL4_VMEnter(seL4_Word *sender)
{
seL4_Word fault;
seL4_Word badge;
@ -313,7 +313,7 @@ seL4_VMEnter(seL4_CPtr vcpu, seL4_Word *sender)
seL4_Word mr2 = seL4_GetMR(2);
seL4_Word mr3 = seL4_GetMR(3);
x64_sys_send_recv(seL4_SysVMEnter, vcpu, &badge, 0, &fault, &mr0, &mr1, &mr2, &mr3);
x64_sys_send_recv(seL4_SysVMEnter, 0, &badge, 0, &fault, &mr0, &mr1, &mr2, &mr3);
seL4_SetMR(0, mr0);
seL4_SetMR(1, mr1);

View file

@ -129,6 +129,7 @@ ${GeneratedLatexDir}/%.tex: ${DoxygenXml}/group__%.xml
generated-latex: ${GeneratedLatexDir}/GeneralSystemCalls.tex \
${GeneratedLatexDir}/DebuggingSystemCalls.tex \
${GeneratedLatexDir}/BenchmarkingSystemCalls.tex \
${GeneratedLatexDir}/X86SystemCalls.tex \
${GeneratedLatexDir}/ObjectApi.tex \
${GeneratedLatexDir}/ObjectApiX86.tex \
${GeneratedLatexDir}/ObjectApiArm.tex \

View file

@ -256,6 +256,10 @@ complete the \apifunc{seL4\_Untyped\_Retype}{untyped_retype} request.
\inputgeneratedapidoc{BenchmarkingSystemCalls}
\clearpage
\subsection{X86 System Calls}
\inputgeneratedapidoc{X86SystemCalls}
\clearpage
\section{Architecture-Independent Object Methods}
\label{sec:kobj_api}
\inputgeneratedapidoc{ObjectApi}

View file

@ -487,4 +487,69 @@ The caller must possess a \obj{Domain} cap and the thread's \obj{TCB} cap.
The initial thread starts with a \obj{Domain} cap (see
\autoref{sec:messageinfo}).
\section{Virtualisation}
\label{sec:virt}
Hardware execution virtualisation is supported on specific arm and x86 platforms. The interface is exposed through a series
of kernel objects, invocations and syscalls that allow the user to take advantage of hardware
virtualisation features.
Hardware virtualisation allows for a thread to perform instructions and operations as if it were
running at a higher privilege level. As higher privilege levels typically have access to
additional machine registers and other pieces of state a \obj{VCPU} object is introduced to act
as storage for this state. For simplicity we refer to this virtualised higher privileged level as
'guest mode'. \obj{VCPU}s are bound in a one-to-one relationship with a \obj{TCB} in order
to provide a thread with this ability to run in higher privilege mode. See the section on
ARM or x86 for more precise details.
\obj{VCPU} objects also have additional, architecture specific, invocations for manipulating
the additional state or other virtualisation controls provided by the hardware. Binding of
a \obj{VCPU} to a \obj{TCB} is done by an invocation on the \obj{VCPU} only, and not the \obj{TCB}.
The provided objects and invocations are, generally speaking, the thinnest possible shim over
the underlying hardware primitives and operations. As a result an in depth familiarity with
the underlying architecture specific harwdare mechanisms is required to use these objects, and
such familiarity is therefore assumed in description.
\subsection{ARM}
When a \obj{TCB} has a bound \obj{VCPU} it is allowed to have the mode portion of the
\texttt{cpsr} register set to values other than \texttt{user}. Specifically it may have any value other than
\texttt{hypervisor}.
TODO: this section needs more detail
\subsection{x86}
A \obj{TCB} with a bound \obj{VCPU} has two execution modes; one is the original thread just as
if there was no bound \obj{VCPU}, and the other is the guest mode execution using the
\obj{VCPU}. Switching from regular execution mode into the guest execution mode is
done by using the \apifunc{seL4\_VMEnter}{sel4_vmenter} syscall. Executing this syscall causes the thread, whenever
it is scheduled thereafter, to execute using the higher privlidged mode controlled by the \obj{VCPU}.
Should the guest execution mode generate any kind of fault, or if a message arrives
on the \obj{TCB}s bound notification, the \obj{TCB} will be switched back to regular mode
and the \apifunc{seL4\_VMEnter}{sel4_vmenter} syscall will return with a message indicating the reason for return.
\obj{VCPU} state and execution is controlled through the \apifunc{seL4\_VCPU\_ReadVMCS}{x86_vcpu_readvmcs}
and \apifunc{seL4\_VCPU\_WriteVMCS}{x86_vcpu_writevmcs} invocations.
These are very thin wrappers around the hardware \texttt{vmread} and \texttt{vmwrite} instructions and the kernel
merely does enough validation on the parameters to ensure the \obj{VCPU} is not configured
to run in such a way as to violate any kernel properties. For example, it is not possible to
disable the use of External Interrupt Exiting, as this would prevent the kernel from receiving
timer interrupts and allow the thread to monopolise CPU time.
Memory access of the guest execution mode is controlled by requiring the use of Extended
Page Tables (EPT). A series of EPT related paging structure objects (\obj{EPTPML4}, \obj{EPTPDPT}, \obj{EPTPD}, \obj{EPTPT})
exist and are manipulated in exactly the same manner as the objects for the regular virtual
address space. Once constructed a \obj{TCB} can be given an \obj{EPTPML4} as an EPT root with \apifunc{seL4\_TCB\_SetEPTRoot}{x86_set_eptroot},
which serves as the vspace root when executing in guest mode, with the vspace root set
with \apifunc{seL4\_TCB\_SetSPace}{tcb_setspace} or \apifunc{seL4\_TCB\_Configure}{tcb_configure}
continuing to provide translation when the TCB is executing in its normal mode.
Direct access to I/O ports can be given to the privlidged execution mode through the
\apifunc{seL4\_X86\_VCPU\_EnableIOPort}{x86_vcpu_enableioport} invocation and allows the provided I/O port capability to be
linked to the VCPU, and a subset of its I/O port range to be made accessible to the \obj{VCPU}.
Linking means that an I/O port capability can only be used in a single \apifunc{seL4\_X86\_VCPU\_EnableIOPort}{x86_vcpu_enableioport}
invocation and a second invocation will undo the previous one. The link also means that
if the I/O port capability is deleted for any reason the access will be correspondingly removed
from the \obj{VCPU}.

View file

@ -20,6 +20,8 @@ import sys
import os
import re
from bs4 import BeautifulSoup
import six
# Dict mapping characters to their escape sequence in latex
LATEX_ESCAPE_PATTERNS = {
"_": "\\_",
@ -53,7 +55,7 @@ def get_text(soup, escape=True):
if isinstance(soup, str):
string = soup
elif isinstance(soup, unicode):
elif isinstance(soup, six.string_types):
string = str(soup)
elif soup.string:
string = str(soup.string)
@ -154,11 +156,11 @@ def parse_detailed_desc(parent, ref_dict):
names = parent.find_all('declname')
# the first type is the return type
ret_type = types_iter.next()
ret_type = six.next(types_iter)
# the rest are parameters
for n in names:
param_type = types_iter.next().text
param_type = six.next(types_iter).text
if param_type == "void":
continue
params[str(n.text)] = {"type": param_type}

View file

@ -252,7 +252,7 @@ map_kernel_window(
#ifdef CONFIG_BENCHMARK_USE_KERNEL_LOG_BUFFER
/* Map global page table for the log buffer */
pde = pde_pde_small_new(
pde = pde_pde_pt_new(
pptr_to_paddr(ia32KSGlobalLogPT), /* pt_base_address */
0, /* avl */
0, /* accessed */
@ -278,7 +278,7 @@ map_kernel_window(
#endif /* ENABLE_SMP_SUPPORT */
/* map page table of last 4M of virtual address space to page directory */
pde = pde_pde_small_new(
pde = pde_pde_pt_new(
pptr_to_paddr(ia32KSGlobalPT), /* pt_base_address */
0, /* avl */
0, /* accessed */
@ -545,7 +545,7 @@ pde_t CONST makeUserPDELargePage(paddr_t paddr, vm_attributes_t vm_attr, vm_righ
pde_t CONST makeUserPDEPageTable(paddr_t paddr, vm_attributes_t vm_attr)
{
return pde_pde_small_new(
return pde_pde_pt_new(
paddr, /* pt_base_address */
0, /* avl */
0, /* accessed */
@ -576,7 +576,7 @@ pde_t CONST makeUserPDELargePageInvalid(void)
pde_t CONST makeUserPDEPageTableInvalid(void)
{
return pde_pde_small_new(
return pde_pde_pt_new(
0, /* pt_base_address */
0, /* avl */
0, /* accessed */

View file

@ -113,7 +113,7 @@ map_it_pt_cap(cap_t vspace_cap, cap_t pt_cap)
vptr_t vptr = cap_page_table_cap_get_capPTMappedAddress(pt_cap);
assert(cap_page_table_cap_get_capPTIsMapped(pt_cap));
*(pd + (vptr >> seL4_LargePageBits)) = pde_pde_small_new(
*(pd + (vptr >> seL4_LargePageBits)) = pde_pde_pt_new(
pptr_to_paddr(pt), /* pt_base_address */
0, /* avl */
0, /* accessed */
@ -143,7 +143,7 @@ map_it_frame_cap(cap_t pd_cap, cap_t frame_cap)
assert(cap_frame_cap_get_capFMappedASID(frame_cap) != 0);
pd += (vptr >> seL4_LargePageBits);
pt = paddr_to_pptr(pde_pde_small_ptr_get_pt_base_address(pd));
pt = paddr_to_pptr(pde_pde_pt_ptr_get_pt_base_address(pd));
*(pt + ((vptr & MASK(seL4_LargePageBits)) >> seL4_PageBits)) = pte_new(
pptr_to_paddr(frame), /* page_base_address */
0, /* avl */

View file

@ -127,7 +127,7 @@ map_kernel_window(
1 /* present */
);
/* put the PT into the PD */
x64KSGlobalPD[0] = pde_pde_small_new(
x64KSGlobalPD[0] = pde_pde_pt_new(
0, /* xd */
kpptr_to_paddr(x64KSGlobalPT),
0, /* accessed */
@ -226,7 +226,7 @@ map_kernel_window(
);
/* put the PT into the PD */
x64KSGlobalPDs[BIT(PDPT_INDEX_BITS) - 1][0] = pde_pde_small_new(
x64KSGlobalPDs[BIT(PDPT_INDEX_BITS) - 1][0] = pde_pde_pt_new(
0, /* xd */
kpptr_to_paddr(x64KSGlobalPT),
0, /* accessed */
@ -501,8 +501,8 @@ map_it_frame_cap(cap_t pd_cap, cap_t frame_cap)
assert(pdpte_pdpte_pd_ptr_get_present(pdpt));
pd = paddr_to_pptr(pdpte_pdpte_pd_ptr_get_pd_base_address(pdpt));
pd += GET_PD_INDEX(vptr);
assert(pde_pde_small_ptr_get_present(pd));
pt = paddr_to_pptr(pde_pde_small_ptr_get_pt_base_address(pd));
assert(pde_pde_pt_ptr_get_present(pd));
pt = paddr_to_pptr(pde_pde_pt_ptr_get_pt_base_address(pd));
*(pt + GET_PT_INDEX(vptr)) = pte_new(
0, /* xd */
pptr_to_paddr(pptr), /* page_base_address */
@ -578,7 +578,7 @@ map_it_pt_cap(cap_t vspace_cap, cap_t pt_cap)
pdpt += GET_PDPT_INDEX(vptr);
assert(pdpte_pdpte_pd_ptr_get_present(pdpt));
pd = paddr_to_pptr(pdpte_pdpte_pd_ptr_get_pd_base_address(pdpt));
*(pd + GET_PD_INDEX(vptr)) = pde_pde_small_new(
*(pd + GET_PD_INDEX(vptr)) = pde_pde_pt_new(
0, /* xd */
pptr_to_paddr(pt), /* pt_base_address */
0, /* accessed */
@ -871,7 +871,7 @@ pde_t CONST
makeUserPDEPageTable(paddr_t paddr, vm_attributes_t vm_attr)
{
return pde_pde_small_new(
return pde_pde_pt_new(
0, /* xd */
paddr, /* pt_base_address */
0, /* accessed */
@ -904,7 +904,7 @@ makeUserPDELargePageInvalid(void)
pde_t CONST
makeUserPDEPageTableInvalid(void)
{
return pde_pde_small_new(
return pde_pde_pt_new(
0, /* xd */
0, /* pt_base_addr */
0, /* accessed */

View file

@ -173,8 +173,8 @@ lookupEPTPTSlot(ept_pml4e_t* pml4, vptr_t vptr)
return ret;
}
if ((ept_pde_ptr_get_page_size(lu_ret.pdSlot) != ept_pde_ept_pde_4k) ||
!ept_pde_ept_pde_4k_ptr_get_read(lu_ret.pdSlot)) {
if ((ept_pde_ptr_get_page_size(lu_ret.pdSlot) != ept_pde_ept_pde_pt) ||
!ept_pde_ept_pde_pt_ptr_get_read(lu_ret.pdSlot)) {
current_lookup_fault = lookup_fault_missing_capability_new(22);
ret.ptSlot = NULL;
@ -182,7 +182,7 @@ lookupEPTPTSlot(ept_pml4e_t* pml4, vptr_t vptr)
return ret;
}
ept_pte_t *pt = paddr_to_pptr(ept_pde_ept_pde_4k_ptr_get_pt_base_address(lu_ret.pdSlot));
ept_pte_t *pt = paddr_to_pptr(ept_pde_ept_pde_pt_ptr_get_pt_base_address(lu_ret.pdSlot));
uint32_t index = GET_EPT_PT_INDEX(vptr);
ret.ptSlot = pt + index;
@ -620,8 +620,8 @@ EPTPageTableMapped(asid_t asid, vptr_t vaddr, ept_pte_t *pt)
return ret;
}
if (ept_pde_ptr_get_page_size(find_ret.pdSlot) == ept_pde_ept_pde_4k
&& ptrFromPAddr(ept_pde_ept_pde_4k_ptr_get_pt_base_address(find_ret.pdSlot)) == pt) {
if (ept_pde_ptr_get_page_size(find_ret.pdSlot) == ept_pde_ept_pde_pt
&& ptrFromPAddr(ept_pde_ept_pde_pt_ptr_get_pt_base_address(find_ret.pdSlot)) == pt) {
ret.pml4 = asid_ret.ept;
ret.pdSlot = find_ret.pdSlot;
ret.status = EXCEPTION_NONE;
@ -642,7 +642,7 @@ unmapEPTPageTable(asid_t asid, vptr_t vaddr, ept_pte_t *pt)
lu_ret = EPTPageTableMapped(asid, vaddr, pt);
if (lu_ret.status == EXCEPTION_NONE) {
*lu_ret.pdSlot = ept_pde_ept_pde_4k_new(
*lu_ret.pdSlot = ept_pde_ept_pde_pt_new(
0, /* pt_base_address */
0, /* avl_cte_depth */
0, /* execute */
@ -767,8 +767,8 @@ decodeX86EPTPTInvocation(
return EXCEPTION_SYSCALL_ERROR;
}
if (((ept_pde_ptr_get_page_size(lu_ret.pdSlot) == ept_pde_ept_pde_4k) &&
ept_pde_ept_pde_4k_ptr_get_read(lu_ret.pdSlot)) ||
if (((ept_pde_ptr_get_page_size(lu_ret.pdSlot) == ept_pde_ept_pde_pt) &&
ept_pde_ept_pde_pt_ptr_get_read(lu_ret.pdSlot)) ||
((ept_pde_ptr_get_page_size(lu_ret.pdSlot) == ept_pde_ept_pde_2m) &&
ept_pde_ept_pde_2m_ptr_get_read(lu_ret.pdSlot))) {
userError("X86EPTPTMap: Page table already mapped here");
@ -777,7 +777,7 @@ decodeX86EPTPTInvocation(
}
paddr = pptr_to_paddr((void*)(cap_ept_pt_cap_get_capPTBasePtr(cap)));
pde = ept_pde_ept_pde_4k_new(
pde = ept_pde_ept_pde_pt_new(
paddr,/* pt_base_address */
0, /* avl_cte_depth */
1, /* execute */
@ -944,15 +944,15 @@ decodeX86EPTPageMap(
}
if ((ept_pde_ptr_get_page_size(lu_ret.pdSlot) == ept_pde_ept_pde_4k) &&
ept_pde_ept_pde_4k_ptr_get_read(lu_ret.pdSlot)) {
if ((ept_pde_ptr_get_page_size(lu_ret.pdSlot) == ept_pde_ept_pde_pt) &&
ept_pde_ept_pde_pt_ptr_get_read(lu_ret.pdSlot)) {
userError("X86EPTPageMap: Page table already present.");
current_syscall_error.type = seL4_DeleteFirst;
return EXCEPTION_SYSCALL_ERROR;
}
if (LARGE_PAGE_BITS != EPT_PD_INDEX_OFFSET &&
(ept_pde_ptr_get_page_size(lu_ret.pdSlot + 1) == ept_pde_ept_pde_4k) &&
ept_pde_ept_pde_4k_ptr_get_read(lu_ret.pdSlot + 1)) {
(ept_pde_ptr_get_page_size(lu_ret.pdSlot + 1) == ept_pde_ept_pde_pt) &&
ept_pde_ept_pde_pt_ptr_get_read(lu_ret.pdSlot + 1)) {
userError("X86EPTPageMap: Page table already present.");
current_syscall_error.type = seL4_DeleteFirst;
return EXCEPTION_SYSCALL_ERROR;

View file

@ -626,8 +626,8 @@ lookupPTSlot_ret_t lookupPTSlot(vspace_root_t *vspace, vptr_t vptr)
ret.status = pdSlot.status;
return ret;
}
if ((pde_ptr_get_page_size(pdSlot.pdSlot) != pde_pde_small) ||
!pde_pde_small_ptr_get_present(pdSlot.pdSlot)) {
if ((pde_ptr_get_page_size(pdSlot.pdSlot) != pde_pde_pt) ||
!pde_pde_pt_ptr_get_present(pdSlot.pdSlot)) {
current_lookup_fault = lookup_fault_missing_capability_new(PAGE_BITS + PT_INDEX_BITS);
ret.ptSlot = NULL;
ret.status = EXCEPTION_LOOKUP_FAULT;
@ -637,7 +637,7 @@ lookupPTSlot_ret_t lookupPTSlot(vspace_root_t *vspace, vptr_t vptr)
pte_t* ptSlot;
word_t ptIndex;
pt = paddr_to_pptr(pde_pde_small_ptr_get_pt_base_address(pdSlot.pdSlot));
pt = paddr_to_pptr(pde_pde_pt_ptr_get_pt_base_address(pdSlot.pdSlot));
ptIndex = (vptr >> PAGE_BITS) & MASK(PT_INDEX_BITS);
ptSlot = pt + ptIndex;
@ -776,9 +776,9 @@ void unmapPageTable(asid_t asid, vptr_t vaddr, pte_t* pt)
}
/* check if the PD actually refers to the PT */
if (! (pde_ptr_get_page_size(lu_ret.pdSlot) == pde_pde_small &&
pde_pde_small_ptr_get_present(lu_ret.pdSlot) &&
(pde_pde_small_ptr_get_pt_base_address(lu_ret.pdSlot) == pptr_to_paddr(pt)))) {
if (! (pde_ptr_get_page_size(lu_ret.pdSlot) == pde_pde_pt &&
pde_pde_pt_ptr_get_present(lu_ret.pdSlot) &&
(pde_pde_pt_ptr_get_pt_base_address(lu_ret.pdSlot) == pptr_to_paddr(pt)))) {
return;
}
@ -985,8 +985,8 @@ exception_t decodeX86FrameInvocation(
pdeSlot = lu_ret.pdSlot;
/* check for existing page table */
if ((pde_ptr_get_page_size(pdeSlot) == pde_pde_small) &&
(pde_pde_small_ptr_get_present(pdeSlot))) {
if ((pde_ptr_get_page_size(pdeSlot) == pde_pde_pt) &&
(pde_pde_pt_ptr_get_present(pdeSlot))) {
current_syscall_error.type = seL4_DeleteFirst;
return EXCEPTION_SYSCALL_ERROR;
@ -1123,8 +1123,8 @@ exception_t decodeX86FrameInvocation(
}
pdeSlot = lu_ret.pdSlot;
if ((pde_ptr_get_page_size(pdeSlot) == pde_pde_small) &&
(pde_pde_small_ptr_get_present(pdeSlot))) {
if ((pde_ptr_get_page_size(pdeSlot) == pde_pde_pt) &&
(pde_pde_pt_ptr_get_present(pdeSlot))) {
current_syscall_error.type = seL4_DeleteFirst;
return EXCEPTION_SYSCALL_ERROR;
@ -1321,7 +1321,7 @@ decodeX86PageTableInvocation(
return EXCEPTION_SYSCALL_ERROR;
}
if (((pde_ptr_get_page_size(pdSlot.pdSlot) == pde_pde_small) && pde_pde_small_ptr_get_present(pdSlot.pdSlot)) ||
if (((pde_ptr_get_page_size(pdSlot.pdSlot) == pde_pde_pt) && pde_pde_pt_ptr_get_present(pdSlot.pdSlot)) ||
((pde_ptr_get_page_size(pdSlot.pdSlot) == pde_pde_large) && pde_pde_large_ptr_get_present(pdSlot.pdSlot))) {
current_syscall_error.type = seL4_DeleteFirst;

View file

@ -127,8 +127,8 @@ static void sendPD(unsigned long address)
for (i = 0; i < PD_READ_SIZE; i++) {
pde_t pde = start[i];
exists = 1;
if (pde_get_page_size(pde) == pde_pde_small && (pde_pde_small_get_pt_base_address(pde) == 0 ||
!pde_pde_small_get_present(pde) || !pde_pde_small_get_super_user(pde))) {
if (pde_get_page_size(pde) == pde_pde_pt && (pde_pde_pt_get_pt_base_address(pde) == 0 ||
!pde_pde_pt_get_present(pde) || !pde_pde_pt_get_super_user(pde))) {
exists = 0;
} else if (pde_get_page_size(pde) == pde_pde_large && (pde_pde_large_get_page_base_address(pde) == 0 ||
!pde_pde_large_get_present(pde) || !pde_pde_large_get_super_user(pde))) {

View file

@ -44,11 +44,5 @@ word_t sanitiseRegister(register_t reg, word_t v, bool_t archInfo)
/* remove any other bits that shouldn't be set */
v &= FLAGS_MASK;
}
if (reg == TLS_BASE) {
/* forbid users from setting a TLS_BASE that is in the kernel window */
if (v > PPTR_USER_TOP) {
v = PPTR_USER_TOP;
}
}
return v;
}

View file

@ -22,7 +22,7 @@ config_string(KernelMaxRMRREntries MAX_RMRR_ENTRIES
"Setsthe maximum number of Reserved Memory Region Reporting structures we support \
recording from the ACPI tables"
DEFAULT 32
DEPENDS "KernelIOMMU" DEFAULT_DISABLED 0
DEPENDS "KernelIOMMU" DEFAULT_DISABLED 1
UNQUOTE
)

View file

@ -36,10 +36,17 @@ import umm
# Whether debugging is enabled (turn on with command line option --debug).
DEBUG = False
# parametrisation for the win
return_name = 'ret__unsigned'
# name of locale the bitfield proofs should be in
loc_name = 'kernel_all_substitute'
# Isabelle word size suffixes for return value names
ret_name_suffix_map = {8 : '', 16 : '', 32 : '', 64 : '_longlong'}
def return_name(base):
# name of return value for standard word sizes
return 'ret__unsigned' + ret_name_suffix_map[base]
# Headers to include depending on which environment we are generating code for.
INCLUDES = {
'sel4':['assert.h', 'config.h', 'stdint.h', 'util.h'],
@ -272,21 +279,21 @@ ptr_reader_template = \
writer_template = \
"""%(inline)s %(block)s_t CONST
%(block)s_set_%(field)s(%(block)s_t %(block)s, %(type)s v) {
%(block)s_set_%(field)s(%(block)s_t %(block)s, %(type)s v%(base)d) {
/* fail if user has passed bits that we will override */
%(assert)s((((~0x%(mask)x %(r_shift_op)s %(shift)d ) | 0x%(high_bits)x) & v) == ((%(sign_extend)d && (v & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(assert)s((((~0x%(mask)x %(r_shift_op)s %(shift)d ) | 0x%(high_bits)x) & v%(base)d) == ((%(sign_extend)d && (v%(base)d & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(block)s.words[%(index)d] &= ~0x%(mask)x%(suf)s;
%(block)s.words[%(index)d] |= (v %(w_shift_op)s %(shift)d) & 0x%(mask)x%(suf)s;
%(block)s.words[%(index)d] |= (v%(base)d %(w_shift_op)s %(shift)d) & 0x%(mask)x%(suf)s;
return %(block)s;
}"""
ptr_writer_template = \
"""%(inline)s void
%(block)s_ptr_set_%(field)s(%(block)s_t *%(block)s_ptr, %(type)s v) {
%(block)s_ptr_set_%(field)s(%(block)s_t *%(block)s_ptr, %(type)s v%(base)d) {
/* fail if user has passed bits that we will override */
%(assert)s((((~0x%(mask)x %(r_shift_op)s %(shift)d) | 0x%(high_bits)x) & v) == ((%(sign_extend)d && (v & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(assert)s((((~0x%(mask)x %(r_shift_op)s %(shift)d) | 0x%(high_bits)x) & v%(base)d) == ((%(sign_extend)d && (v%(base)d & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(block)s_ptr->words[%(index)d] &= ~0x%(mask)x%(suf)s;
%(block)s_ptr->words[%(index)d] |= (v %(w_shift_op)s """ \
%(block)s_ptr->words[%(index)d] |= (v%(base)d %(w_shift_op)s """ \
"""%(shift)d) & 0x%(mask)x;
}"""
@ -344,31 +351,31 @@ ptr_union_reader_template = \
union_writer_template = \
"""%(inline)s %(union)s_t CONST
%(union)s_%(block)s_set_%(field)s(%(union)s_t %(union)s, %(type)s v) {
%(union)s_%(block)s_set_%(field)s(%(union)s_t %(union)s, %(type)s v%(base)d) {
%(assert)s(((%(union)s.words[%(tagindex)d] >> %(tagshift)d) & 0x%(tagmask)x) ==
%(union)s_%(block)s);
/* fail if user has passed bits that we will override */
%(assert)s((((~0x%(mask)x%(suf)s %(r_shift_op)s %(shift)d ) | 0x%(high_bits)x) & v) == ((%(sign_extend)d && (v & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(assert)s((((~0x%(mask)x%(suf)s %(r_shift_op)s %(shift)d ) | 0x%(high_bits)x) & v%(base)d) == ((%(sign_extend)d && (v%(base)d & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(union)s.words[%(index)d] &= ~0x%(mask)x%(suf)s;
%(union)s.words[%(index)d] |= (v %(w_shift_op)s %(shift)d) & 0x%(mask)x%(suf)s;
%(union)s.words[%(index)d] |= (v%(base)d %(w_shift_op)s %(shift)d) & 0x%(mask)x%(suf)s;
return %(union)s;
}"""
ptr_union_writer_template = \
"""%(inline)s void
%(union)s_%(block)s_ptr_set_%(field)s(%(union)s_t *%(union)s_ptr,
%(type)s v) {
%(type)s v%(base)d) {
%(assert)s(((%(union)s_ptr->words[%(tagindex)d] >> """ \
"""%(tagshift)d) & 0x%(tagmask)x) ==
%(union)s_%(block)s);
/* fail if user has passed bits that we will override */
%(assert)s((((~0x%(mask)x%(suf)s %(r_shift_op)s %(shift)d) | 0x%(high_bits)x) & v) == ((%(sign_extend)d && (v & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(assert)s((((~0x%(mask)x%(suf)s %(r_shift_op)s %(shift)d) | 0x%(high_bits)x) & v%(base)d) == ((%(sign_extend)d && (v%(base)d & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(union)s_ptr->words[%(index)d] &= ~0x%(mask)x%(suf)s;
%(union)s_ptr->words[%(index)d] |= """ \
"""(v %(w_shift_op)s %(shift)d) & 0x%(mask)x%(suf)s;
"""(v%(base)d %(w_shift_op)s %(shift)d) & 0x%(mask)x%(suf)s;
}"""
tag_reader_header_template = \
@ -424,23 +431,23 @@ ptr_tag_reader_footer_template = \
tag_writer_template = \
"""%(inline)s %(union)s_t CONST
%(union)s_set_%(tagname)s(%(union)s_t %(union)s, %(type)s v) {
%(union)s_set_%(tagname)s(%(union)s_t %(union)s, %(type)s v%(base)d) {
/* fail if user has passed bits that we will override */
%(assert)s((((~0x%(mask)x%(suf)s %(r_shift_op)s %(shift)d) | 0x%(high_bits)x) & v) == ((%(sign_extend)d && (v & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(assert)s((((~0x%(mask)x%(suf)s %(r_shift_op)s %(shift)d) | 0x%(high_bits)x) & v%(base)d) == ((%(sign_extend)d && (v%(base)d & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(union)s.words[%(index)d] &= ~0x%(mask)x%(suf)s;
%(union)s.words[%(index)d] |= (v << %(shift)d) & 0x%(mask)x%(suf)s;
%(union)s.words[%(index)d] |= (v%(base)d << %(shift)d) & 0x%(mask)x%(suf)s;
return %(union)s;
}"""
ptr_tag_writer_template = \
"""%(inline)s void
%(union)s_ptr_set_%(tagname)s(%(union)s_t *%(union)s_ptr, %(type)s v) {
%(union)s_ptr_set_%(tagname)s(%(union)s_t *%(union)s_ptr, %(type)s v%(base)d) {
/* fail if user has passed bits that we will override */
%(assert)s((((~0x%(mask)x%(suf)s %(r_shift_op)s %(shift)d) | 0x%(high_bits)x) & v) == ((%(sign_extend)d && (v & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(assert)s((((~0x%(mask)x%(suf)s %(r_shift_op)s %(shift)d) | 0x%(high_bits)x) & v%(base)d) == ((%(sign_extend)d && (v%(base)d & (1%(suf)s << (%(extend_bit)d)))) ? 0x%(high_bits)x : 0));
%(union)s_ptr->words[%(index)d] &= ~0x%(mask)x%(suf)s;
%(union)s_ptr->words[%(index)d] |= (v << %(shift)d) & 0x%(mask)x%(suf)s;
%(union)s_ptr->words[%(index)d] |= (v%(base)d << %(shift)d) & 0x%(mask)x%(suf)s;
}"""
# HOL definition templates
@ -476,7 +483,7 @@ where
union_get_tag_def_entry_template = \
'''if ((index (%(name)s_C.words_C %(name)s) %(tag_index)d)''' \
''' AND %(classmask)d \<noteq> %(classmask)d)
''' AND 0x%(classmask)x \<noteq> 0x%(classmask)x)
then ((index (%(name)s_C.words_C %(name)s) %(tag_index)d)'''\
''' >> %(tag_shift)d) AND mask %(tag_size)d
else '''
@ -492,7 +499,7 @@ union_get_tag_eq_x_def_header_template = \
"(%(name)s_get_tag c = x) = (('''
union_get_tag_eq_x_def_entry_template = \
'''if ((x << %(tag_shift)d) AND %(classmask)d \<noteq> %(classmask)d)
'''if ((x << %(tag_shift)d) AND 0x%(classmask)x \<noteq> 0x%(classmask)x)
then ((index (%(name)s_C.words_C c) %(tag_index)d)''' \
''' >> %(tag_shift)d) AND mask %(tag_size)d
else '''
@ -544,6 +551,7 @@ where
# HOL proof templates
#FIXME: avoid [simp]
struct_lemmas_template = \
'''
lemmas %(name)s_ptr_guards[simp] =
@ -551,6 +559,7 @@ lemmas %(name)s_ptr_guards[simp] =
%(name)s_ptr_words_aligned
%(name)s_ptr_words_ptr_safe'''
# FIXME: move to global theory
defs_global_lemmas = '''
lemma word_sub_mask:
"\<lbrakk> w && m1 = v1; m1 && m2 = m2; v1 && m2 = v2 \<rbrakk>
@ -584,14 +593,14 @@ def ptr_get_template(ptrname):
return ptr_basic_template('get_%(field)s', ptrname, '\<acute>%(ret_name)s :== ', '',
'''\<lbrace>\<acute>%(ret_name)s = ''' \
'''%(name)s_CL.%(field)s_CL ''' \
'''(%(name)s_lift (%(access_path)s))\<rbrace>''') # AND %(mask)s
'''(%(name)s_lift (%(access_path)s))\<rbrace>''')
def ptr_set_template(name, ptrname):
return ptr_basic_template(name, ptrname, '', ', \<acute>v',
return ptr_basic_template(name, ptrname, '', ', \<acute>v%(base)d',
'''{t. \<exists>%(name)s.
%(name)s_lift %(name)s =
%(name)s_lift (%(access_path)s) \<lparr> %(name)s_CL.%(field)s_CL ''' \
''':= \<^bsup>s\<^esup>v AND %(mask)s \<rparr> \<and>
''':= %(sign_extend)s(\<^bsup>s\<^esup>v%(base)d AND %(mask)s) \<rparr> \<and>
t_hrs_' (globals t) = hrs_mem_update (heap_update
(''' + ptrname + ''')
%(update_path)s)
@ -641,16 +650,16 @@ def ptr_union_get_template(ptrname):
'\<and> %(name)s_get_tag %(access_path)s = scast %(name)s_%(block)s',
'''\<lbrace>\<acute>%(ret_name)s = ''' \
'''%(name)s_%(block)s_CL.%(field)s_CL ''' \
'''(%(name)s_%(block)s_lift %(access_path)s)\<rbrace>''') # AND %(mask)s --- given by _lift?
'''(%(name)s_%(block)s_lift %(access_path)s)\<rbrace>''')
def ptr_union_set_template(ptrname):
return ptr_union_basic_template('set_%(field)s', ptrname, '', ', \<acute>v',
return ptr_union_basic_template('set_%(field)s', ptrname, '', ', \<acute>v%(base)d',
'\<and> %(name)s_get_tag %(access_path)s = scast %(name)s_%(block)s',
'''{t. \<exists>%(name)s. ''' \
'''%(name)s_%(block)s_lift %(name)s =
%(name)s_%(block)s_lift %(access_path)s ''' \
'''\<lparr> %(name)s_%(block)s_CL.%(field)s_CL ''' \
''':= \<^bsup>s\<^esup>v AND %(mask)s \<rparr> \<and>
''':= %(sign_extend)s(\<^bsup>s\<^esup>v%(base)d AND %(mask)s) \<rparr> \<and>
%(name)s_get_tag %(name)s = scast %(name)s_%(block)s \<and>
t_hrs_' (globals t) = hrs_mem_update (heap_update
(''' + ptrname + ''')
@ -679,7 +688,7 @@ done'''],
'''lemma %(name)s_ptr_words_aligned:
"c_guard (p::%(name)s_C ptr) \<Longrightarrow>
ptr_aligned ((Ptr &(p\<rightarrow>[''words_C'']))::''' \
'''((word32[%(words)d]) ptr))"''',
'''((word%(base)d[%(words)d]) ptr))"''',
''' apply(fastforce intro:c_guard_ptr_aligned_fl simp:typ_uinfo_t_def)
done'''],
@ -687,7 +696,7 @@ done'''],
'''lemma %(name)s_ptr_words_ptr_safe:
"ptr_safe (p::%(name)s_C ptr) d \<Longrightarrow>
ptr_safe (Ptr &(p\<rightarrow>[''words_C''])::''' \
'''((word32[%(words)d]) ptr)) d"''',
'''((word%(base)d[%(words)d]) ptr)) d"''',
''' apply(fastforce intro:ptr_safe_mono simp:typ_uinfo_t_def)
done'''],
@ -731,11 +740,11 @@ done'''],
apply(simp add:shift_over_ao_dists mask_def ucast_id)
apply(unfold %(name)s_lift_def)
apply(simp add:shift_over_ao_dists)
apply(((simp add:word_ao_dist),
(simp add:word_bw_assocs),
(simp add:multi_shift_simps),
apply(((simp add:word_ao_dist)?,
(simp add:word_bw_assocs)?,
(simp add:multi_shift_simps)?,
(simp add:mask_def word_size))?)
apply(simp add:word_bw_assocs)
apply(simp add:word_bw_assocs)?
done'''],
'ptr_new_spec_direct' : [
@ -754,23 +763,25 @@ done'''],
'''PROC %(name)s_get_%(field)s(\<acute>%(name)s)
\<lbrace>\<acute>%(ret_name)s = ''' \
'''%(name)s_CL.%(field)s_CL ''' \
'''(%(name)s_lift \<^bsup>s\<^esup>%(name)s)\<rbrace>"''', # AND %(mask)s
'''(%(name)s_lift \<^bsup>s\<^esup>%(name)s)\<rbrace>"''',
''' apply(rule allI, rule conseqPre, vcg)
apply(clarsimp)
apply(simp add:%(name)s_lift_def
mask_shift_simps
guard_simps)
apply (simp add: sign_extend_def' mask_def nth_is_and_neq_0 word_bw_assocs shift_over_ao_dists)?
apply(simp add:max_word_def word_and_max_word)?
done'''],
'set_spec' : [
'''lemma (in ''' + loc_name + ''') %(name)s_set_%(field)s_spec:
"\<forall>s. \<Gamma> \<turnstile> {s}
\<acute>ret__struct_%(name)s_C :== ''' \
'''PROC %(name)s_set_%(field)s(\<acute>%(name)s, \<acute>v)
'''PROC %(name)s_set_%(field)s(\<acute>%(name)s, \<acute>v%(base)d)
\<lbrace>%(name)s_lift \<acute>ret__struct_%(name)s_C = ''' \
'''%(name)s_lift \<^bsup>s\<^esup>%(name)s \<lparr> ''' \
'''%(name)s_CL.%(field)s_CL ''' \
''':= \<^bsup>s\<^esup>v AND %(mask) s \<rparr>\<rbrace>"''',
''':= %(sign_extend)s (\<^bsup>s\<^esup>v%(base)d AND %(mask)s) \<rparr>\<rbrace>"''',
''' apply(rule allI, rule conseqPre, vcg)
apply(clarsimp simp:guard_simps ucast_id
%(name)s_lift_def
@ -778,6 +789,8 @@ done'''],
multi_shift_simps word_size
word_ao_dist word_bw_assocs
NOT_eq)
apply (simp add: sign_extend_def' mask_def nth_is_and_neq_0 word_bw_assocs shift_over_ao_dists)?
apply(simp add:max_word_def word_and_max_word)?
done'''],
# where the top level type is the bitfield type --- these are split because they have different proofs
@ -788,8 +801,10 @@ done'''],
apply(clarsimp simp:h_t_valid_clift_Some_iff)
apply(simp add:guard_simps
%(name)s_lift_def
mask_def
typ_heap_simps
ucast_def)
apply (simp add: sign_extend_def' mask_def nth_is_and_neq_0 word_bw_assocs shift_over_ao_dists)?
apply(simp add:max_word_def word_and_max_word)?
done'''],
@ -802,6 +817,8 @@ done'''],
apply(frule clift_subtype, simp, simp, simp)
apply(simp add:h_val_field_clift' typ_heap_simps)
apply(simp add:thread_state_lift_def)
apply (simp add: sign_extend_def' mask_def nth_is_and_neq_0 word_bw_assocs shift_over_ao_dists)?
apply(simp add:max_word_def word_and_max_word)?
apply(simp add:mask_shift_simps)?
done'''],
@ -817,7 +834,9 @@ done'''],
%(name)s_lift_def
typ_heap_simps)
apply(simp add:mask_shift_simps)
apply (simp add: sign_extend_def' mask_def nth_is_and_neq_0 word_bw_assocs shift_over_ao_dists)?
apply(simp add:max_word_def word_and_max_word)?
apply(simp add:mask_shift_simps)?
done'''],
'ptr_set_spec_path' : [
@ -861,16 +880,18 @@ done'''],
apply(simp add:o_def %(name)s_lift_def)
(* Solve bitwise arithmetic *)
apply(simp add:mask_shift_simps)
apply (simp add: sign_extend_def' mask_def nth_is_and_neq_0 word_bw_assocs shift_over_ao_dists)?
apply(simp add:max_word_def word_and_max_word)?
apply(simp add:mask_shift_simps)?
done'''],
'get_tag_spec' : [
'''lemma (in ''' + loc_name + ''') %(name)s_get_%(tagname)s_spec:
"\<forall>s. \<Gamma> \<turnstile> {s}
\<acute>ret__unsigned :== ''' \
\<acute>%(ret_name)s :== ''' \
'''PROC %(name)s_get_%(tagname)s(\<acute>%(name)s)
\<lbrace>\<acute>ret__unsigned = ''' \
\<lbrace>\<acute>%(ret_name)s = ''' \
'''%(name)s_get_tag \<^bsup>s\<^esup>%(name)s\<rbrace>"''',
''' apply(rule allI, rule conseqPre, vcg)
apply(clarsimp)
@ -1028,7 +1049,7 @@ done'''],
\<lbrace>\<acute>%(ret_name)s = ''' \
'''%(name)s_%(block)s_CL.%(field)s_CL ''' \
'''(%(name)s_%(block)s_lift \<^bsup>s\<^esup>%(name)s)''' \
'''\<rbrace>"''', # AND %(mask)s
'''\<rbrace>"''',
''' apply(rule allI, rule conseqPre, vcg)
apply(clarsimp simp:guard_simps)
apply(simp add:%(name)s_%(block)s_lift_def)
@ -1051,7 +1072,9 @@ done'''],
word_ao_dist
word_and_max_word
max_word_def
ucast_def)
ucast_def
sign_extend_def'
nth_is_and_neq_0)
done'''],
'union_set_spec' : [
@ -1061,11 +1084,11 @@ done'''],
'''\<lbrace>s. %(name)s_get_tag \<acute>%(name)s = ''' \
'''scast %(name)s_%(block)s\<rbrace>
\<acute>ret__struct_%(name)s_C :== ''' \
'''PROC %(name)s_%(block)s_set_%(field)s(\<acute>%(name)s, \<acute>v)
'''PROC %(name)s_%(block)s_set_%(field)s(\<acute>%(name)s, \<acute>v%(base)d)
\<lbrace>%(name)s_%(block)s_lift \<acute>ret__struct_%(name)s_C = ''' \
'''%(name)s_%(block)s_lift \<^bsup>s\<^esup>%(name)s \<lparr> ''' \
'''%(name)s_%(block)s_CL.%(field)s_CL ''' \
''':= \<^bsup>s\<^esup>v AND %(mask)s\<rparr> \<and>
''':= %(sign_extend)s (\<^bsup>s\<^esup>v%(base)d AND %(mask)s)\<rparr> \<and>
%(name)s_get_tag \<acute>ret__struct_%(name)s_C = ''' \
'''scast %(name)s_%(block)s\<rbrace>"''',
''' apply(rule allI, rule conseqPre, vcg)
@ -1078,15 +1101,17 @@ done'''],
%(name)s_get_tag_eq_x
%(tag_mask_helpers)s
%(name)s_%(block)s_update_def
%(name)s_tag_defs)
%(name)s_tag_defs
sign_extend_def'
nth_is_and_neq_0)
done'''],
'ptr_union_get_spec_direct' : [
ptr_union_get_template(direct_ptr_name),
''' unfolding ptrval_def
apply(rule allI, rule conseqPre, vcg)
apply(clarsimp simp: typ_heap_simps h_t_valid_clift_Some_iff
guard_simps mask_shift_simps
apply(clarsimp simp: typ_heap_simps h_t_valid_clift_Some_iff guard_simps
mask_shift_simps sign_extend_def' nth_is_and_neq_0
%(name)s_lift_%(block)s %(name)s_%(block)s_lift_def)
done
'''],
@ -1103,7 +1128,7 @@ done
apply(simp add: guard_simps mask_shift_simps)
apply(simp add:%(name)s_%(block)s_lift_def)
apply(subst %(name)s_lift_%(block)s)
apply simp+
apply(simp add: mask_def)+
done
(* ptr_union_get_spec_path *)'''],
@ -1184,6 +1209,22 @@ def emit_named_ptr_proof(fn_name, params, name, type_map, toptps, prf_prefix, su
['\\<lambda>_. ' + name] + path) + '(the (ptrval s))' + ')'
emit_named(fn_name, params, make_proof(prf_prefix + '_path', substs, params.sorry))
def field_mask_proof(high, base_bits, base, size):
if high:
if base_bits == base:
# equivalent to below, but nicer in proofs
return "NOT (mask %d)" % (base - size)
else:
return "(mask %d << %d)" % (size, base_bits - size)
else:
return "mask %d" % size
def sign_extend_proof(high, base_bits, base_sign_extend):
if high and base_sign_extend:
return "sign_extend %d " % (base_bits - 1)
else:
return ""
class TaggedUnion:
def __init__(self, name, tagname, classes, tags):
self.name = name
@ -1275,7 +1316,8 @@ class TaggedUnion:
# Generate struct field pointer proofs
substs = {"name": self.name,
"words": self.multiple}
"words": self.multiple,
"base": self.base}
print(make_proof('words_NULL_proof',
substs, params.sorry), file=output)
@ -1297,7 +1339,7 @@ class TaggedUnion:
# Generate get_tag specs
substs = {"name": self.name,
"tagname": self.tagname,
"ret_name": return_name}
"ret_name": return_name(self.base)}
if not params.skip_modifies:
emit_named("%(name)s_get_%(tagname)s" % substs, params,
@ -1371,14 +1413,11 @@ class TaggedUnion:
if field == self.tagname:
continue
if high:
mask = "NOT (mask %d)" % (self.base - size)
else:
mask = "(mask %d)" % size
mask = field_mask_proof(high, self.base_bits, self.base, size)
sign_extend = sign_extend_proof(high, self.base_bits, self.base_sign_extend)
field_eq_list.append(
"%s_%s_CL.%s_CL = \<^bsup>s\<^esup>%s AND %s" % \
(self.name, ref.name, field, field, mask))
"%s_%s_CL.%s_CL = %s(\<^bsup>s\<^esup>%s AND %s)" % \
(self.name, ref.name, field, sign_extend, field, mask))
field_eqs = ',\n '.join(field_eq_list)
emit_named("%s_%s_new" % (self.name, ref.name), params,
@ -1409,17 +1448,17 @@ class TaggedUnion:
if field == self.tagname:
continue
if high:
mask = "NOT (mask %d)" % (ref.base - size)
else:
mask = "(mask %d)" % size
mask = field_mask_proof(high, self.base_bits, self.base, size)
sign_extend = sign_extend_proof(high, self.base_bits, self.base_sign_extend)
substs = {"name": self.name, \
"block": ref.name, \
"field": field, \
"mask": mask, \
substs = {"name": self.name,
"block": ref.name,
"field": field,
"mask": mask,
"sign_extend": sign_extend,
"tag_mask_helpers" : tag_mask_helpers,
"ret_name": return_name}
"ret_name": return_name(self.base),
"base" : self.base}
# Get modifies spec
if not params.skip_modifies:
@ -1458,7 +1497,7 @@ class TaggedUnion:
"args": ', '.join([
"\<acute>ret__struct_%s_C" % self.name,
"\<acute>%s" % self.name,
"\<acute>v"] )},
"\<acute>v%(base)d"] )},
params.sorry))
emit_named("%s_%s_ptr_set_%s" % (self.name, ref.name, field),
@ -1468,7 +1507,7 @@ class TaggedUnion:
(self.name, ref.name, field), \
"args": ', '.join([
"\<acute>%s_ptr" % self.name,
"\<acute>v"] )},
"\<acute>v%(base)d"] )},
params.sorry))
# Set spec
@ -1590,28 +1629,30 @@ class TaggedUnion:
if field == self.tagname: continue
index = offset // self.base
sign_extend = ""
if high:
shift_op = "<<"
shift = self.base - size - (offset % self.base)
shift = self.base_bits - size - (offset % self.base)
if shift < 0:
shift = -shift
shift_op = ">>"
if self.base_sign_extend:
sign_extend = "sign_extend %d " % (self.base_bits - 1)
else:
shift_op = ">>"
shift = offset % self.base
initialiser = \
"%s_CL.%s_CL = ((index (%s_C.words_C %s) %d) %s %d)" % \
(gen_name(name), field, self.name, self.name, \
"%s_CL.%s_CL = %s(((index (%s_C.words_C %s) %d) %s %d)" % \
(gen_name(name), field, sign_extend, self.name, self.name, \
index, shift_op, shift)
if size < self.base:
if high:
mask = ((1 << size) - 1) << (self.base - size)
else:
mask = (1 << size) - 1
mask = field_mask_proof(high, self.base_bits, self.base, size)
initialiser += " AND " + mask
initialiser += " AND %d" % mask
field_inits.append("\n " + initialiser)
field_inits.append("\n " + initialiser + ")")
if len(field_inits) == 0:
value = gen_name(name, True)
@ -1868,7 +1909,8 @@ class TaggedUnion:
"suf": self.constant_suffix,
"high_bits": high_bits,
"sign_extend": self.base_sign_extend and high,
"extend_bit": self.base_bits - 1}
"extend_bit": self.base_bits - 1,
"base": self.base}
# Reader
emit_named("%s_%s_get_%s" % (self.name, ref.name, field),
@ -2173,31 +2215,34 @@ class Block:
for name in self.visible_order:
offset, size, high = self.field_map[name]
index = offset // self.base
sign_extend = ""
if high:
shift_op = "<<"
shift = self.base - size - (offset % self.base)
shift = self.base_bits - size - (offset % self.base)
if shift < 0:
shift = -shift
shift_op = ">>"
if self.base_sign_extend:
sign_extend = "sign_extend %d " % (self.base_bits - 1)
else:
shift_op = ">>"
shift = offset % self.base
initialiser = \
"%s_CL.%s_CL = ((index (%s_C.words_C %s) %d) %s %d)" % \
(self.name, name, self.name, self.name, \
"%s_CL.%s_CL = %s(((index (%s_C.words_C %s) %d) %s %d)" % \
(self.name, name, sign_extend, self.name, self.name, \
index, shift_op, shift)
if size < self.base:
if high:
mask = ((1 << size) - 1) << (self.base_bits - size)
else:
mask = (1 << size) - 1
initialiser += " AND %d" % mask
field_inits.append(initialiser)
mask = field_mask_proof(high, self.base_bits, self.base, size)
initialiser += " AND " + mask
field_inits.append(initialiser + ")")
print(lift_def_template % \
{"name": self.name, \
"fields": ',\n '.join(field_inits)},
@ -2219,7 +2264,8 @@ class Block:
# Generate struct field pointer proofs
substs = {"name": self.name,
"words": self.multiple}
"words": self.multiple,
"base": self.base}
print(make_proof('words_NULL_proof',
substs, params.sorry), file=output)
@ -2254,13 +2300,11 @@ class Block:
field_eq_list = []
for (field, offset, size, high) in self.fields:
if high:
mask = "NOT (mask %d)" % (self.base - size)
else:
mask = "(mask %d)" % size
mask = field_mask_proof(high, self.base_bits, self.base, size)
sign_extend = sign_extend_proof(high, self.base_bits, self.base_sign_extend)
field_eq_list.append("%s_CL.%s_CL = \<^bsup>s\<^esup>%s AND %s" % \
(self.name, field, field, mask))
field_eq_list.append("%s_CL.%s_CL = %s(\<^bsup>s\<^esup>%s AND %s)" % \
(self.name, field, sign_extend, field, mask))
field_eqs = ',\n '.join(field_eq_list)
emit_named("%s_new" % self.name, params,
@ -2279,15 +2323,15 @@ class Block:
# Generate get/set specs
for (field, offset, size, high) in self.fields:
if high:
mask = "NOT (mask %d)" % (self.base - size)
else:
mask = "(mask %d)" % size
mask = field_mask_proof(high, self.base_bits, self.base, size)
sign_extend = sign_extend_proof(high, self.base_bits, self.base_sign_extend)
substs = {"name": self.name, \
"field": field, \
"mask": mask,
"ret_name": return_name}
"sign_extend": sign_extend,
"ret_name": return_name(self.base),
"base": self.base}
if not params.skip_modifies:
# Get modifies spec
@ -2321,7 +2365,7 @@ class Block:
"args": ', '.join([
"\<acute>ret__struct_%s_C" % self.name,
"\<acute>%s" % self.name,
"\<acute>v"] )},
"\<acute>v%(base)d"] )},
params.sorry))
emit_named("%s_ptr_set_%s" % (self.name, field), params,
@ -2329,7 +2373,7 @@ class Block:
{"fun_name": "%s_ptr_set_%s" % (self.name, field), \
"args": ', '.join([
"\<acute>%s_ptr" % self.name,
"\<acute>v"] )},
"\<acute>v%(base)d"] )},
params.sorry))
@ -2465,7 +2509,8 @@ class Block:
"suf": self.constant_suffix, \
"high_bits": high_bits, \
"sign_extend": self.base_sign_extend and high,
"extend_bit": self.base_bits - 1}
"extend_bit": self.base_bits - 1,
"base": self.base}
# Reader
emit_named("%s_get_%s" % (self.name, field), params,
@ -2625,7 +2670,11 @@ if __name__ == '__main__':
unions = {}
_, block_map, union_map = yacc.parse(input=in_file.read(), lexer=lexer)
base_list = [8, 16, 32, 64]
suffix_map = {8 : 'ul', 16 : 'ul', 32 : 'ul', 64 : 'ull'}
# assumes that unsigned int = 32 bit on 32-bit and 64-bit platforms,
# and that unsigned long long = 64 bit on 64-bit platforms.
# Should still work fine if ull = 128 bit, but will not work
# if unsigned int is less than 32 bit.
suffix_map = {8 : 'u', 16 : 'u', 32 : 'u', 64 : 'ull'}
for base_info, block_list in block_map.items():
base, base_bits, base_sign_extend = base_info
for name, b in block_list.items():
@ -2682,9 +2731,11 @@ if __name__ == '__main__':
if options.hol_defs:
# Fetch kernel
if options.multifile_base is None:
print("theory %s_defs imports \"%s/KernelState_C\" begin" % (
module_name, os.path.relpath(options.cspec_dir,
print("theory %s_defs" % module_name, file=out_file)
print("imports \"%s/KernelState_C\"" % (
os.path.relpath(options.cspec_dir,
os.path.dirname(out_file.filename))), file=out_file)
print("begin", file=out_file)
print(file=out_file)
print(defs_global_lemmas, file=out_file)
@ -2695,9 +2746,9 @@ if __name__ == '__main__':
print("end", file=out_file)
else:
print("theory %s_defs imports" % module_name,
file=out_file)
print("\"%s/KernelState_C\"" % (
print("theory %s_defs" % module_name, file=out_file)
print("imports", file=out_file)
print(" \"%s/KernelState_C\"" % (
os.path.relpath(options.cspec_dir,
os.path.dirname(out_file.filename))), file=out_file)
for e in blocks.values() + unions.values():
@ -2744,14 +2795,10 @@ if __name__ == '__main__':
type_map[tp] = (toptp, path)
if options.multifile_base is None:
print(\
"theory %s_proofs imports %s_defs \"%s/KernelState_C\" begin" % (
module_name, module_name,
os.path.relpath(options.cspec_dir,
os.path.dirname(out_file.filename))),
file=out_file)
print("theory %s_proofs" % module_name, file=out_file)
print("imports %s_defs" % module_name, file=out_file)
print("begin", file=out_file)
print(file=out_file)
print(file=out_file)
for e in blocks.values() + unions.values():
@ -2760,12 +2807,8 @@ if __name__ == '__main__':
print("end", file=out_file)
else:
# top types are broken here.
print("theory %s_proofs imports" % module_name, file=out_file)
print(" \"%s/KernelState_C\"" % (
os.path.relpath(options.cspec_dir,
os.path.dirname(out_file.filename))),
file=out_file)
print("theory %s_proofs" % module_name, file=out_file)
print("imports", file=out_file)
for e in blocks.values() + unions.values():
print(" %s_%s_proofs" % (module_name, e.name),
file=out_file)
@ -2781,10 +2824,8 @@ if __name__ == '__main__':
e.name + "_proofs" + ".thy")
print(("theory %s imports "
+ "%s_%s_defs \"%s/KernelState_C\" begin") % (
submodule_name, base_filename, e.name,
os.path.relpath(options.cspec_dir,
os.path.dirname(out_file.filename))),
+ "%s_%s_defs begin") % (
submodule_name, base_filename, e.name),
file=out_file)
print(file=out_file)

View file

@ -133,7 +133,6 @@ function(GenThyBFTarget args target_name target_file pbf_path pbf_target prunes
foreach(prune IN LISTS prunes)
list(APPEND args "--prune" "${prune}")
endforeach()
list(APPEND deps "${CSPEC_DIR}/Kernel_C.thy" ${prunes})
GenBFTarget("${args}" "${target_name}" "${target_file}" "${pbf_path}" "${pbf_target}" "${deps}")
endfunction(GenThyBFTarget)