From 3775341b9b09a3c5cc404307c632d39fbbaae42d Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Wed, 4 Mar 2015 15:42:16 +1100 Subject: [PATCH 01/19] libsel4: Remove unused right seL4_Transfer_Mint. --- libsel4/include/sel4/types.h | 1 - 1 file changed, 1 deletion(-) diff --git a/libsel4/include/sel4/types.h b/libsel4/include/sel4/types.h index 42afdfe40..6d81f58a1 100644 --- a/libsel4/include/sel4/types.h +++ b/libsel4/include/sel4/types.h @@ -43,7 +43,6 @@ typedef enum { seL4_CanRead = 0x02, seL4_CanGrant = 0x04, seL4_AllRights = 0x07, /* seL4_CanWrite | seL4_CanRead | seL4_CanGrant */ - seL4_Transfer_Mint = 0x100, SEL4_FORCE_LONG_ENUM(seL4_CapRights), } seL4_CapRights; From 86751e48f4f13a87ba8c539dce9cd23d6896dde5 Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Thu, 26 Feb 2015 12:22:40 +1100 Subject: [PATCH 02/19] ARM: Set the XN bit on kernel mappings that do not need to be executable. This covers the kernel stack, globals frame and device memory. We shouldn't be executing in any of these pages, so functionality should be unaffected. This is primarily a debugging aid. --- src/arch/arm/kernel/vspace.c | 4 ++-- src/plat/allwinnerA20/machine/hardware.c | 8 ++++---- src/plat/am335x/machine/hardware.c | 8 ++++---- src/plat/apq8064/machine/hardware.c | 8 ++++---- src/plat/exynos4/machine/hardware.c | 10 +++++----- src/plat/exynos5/machine/hardware.c | 8 ++++---- src/plat/imx31/machine/hardware.c | 8 ++++---- src/plat/imx6/machine/hardware.c | 8 ++++---- src/plat/omap3/machine/hardware.c | 6 +++--- src/plat/zynq7000/machine/hardware.c | 8 ++++---- 10 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/arch/arm/kernel/vspace.c b/src/arch/arm/kernel/vspace.c index 07ba5ddd4..b8d68f2bb 100644 --- a/src/arch/arm/kernel/vspace.c +++ b/src/arch/arm/kernel/vspace.c @@ -279,7 +279,7 @@ map_kernel_window(void) PPTR_GLOBALS_PAGE, VMReadOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ true, /* armParityEnabled */ true /* armPageCacheable */ ) @@ -291,7 +291,7 @@ map_kernel_window(void) PPTR_KERNEL_STACK, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ true, /* armParityEnabled */ true /* armPageCacheable */ ) diff --git a/src/plat/allwinnerA20/machine/hardware.c b/src/plat/allwinnerA20/machine/hardware.c index 1648d2915..5d3e87413 100755 --- a/src/plat/allwinnerA20/machine/hardware.c +++ b/src/plat/allwinnerA20/machine/hardware.c @@ -83,7 +83,7 @@ map_kernel_devices(void) TIMER0_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -95,7 +95,7 @@ map_kernel_devices(void) GIC_CONTROLLER_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -105,7 +105,7 @@ map_kernel_devices(void) GIC_DISTRIBUTOR_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -118,7 +118,7 @@ map_kernel_devices(void) UART0_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) diff --git a/src/plat/am335x/machine/hardware.c b/src/plat/am335x/machine/hardware.c index e1ed27946..f94065481 100644 --- a/src/plat/am335x/machine/hardware.c +++ b/src/plat/am335x/machine/hardware.c @@ -76,7 +76,7 @@ map_kernel_devices(void) DMTIMER0_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -88,7 +88,7 @@ map_kernel_devices(void) INTC_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -100,7 +100,7 @@ map_kernel_devices(void) WDT1_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -113,7 +113,7 @@ map_kernel_devices(void) UART0_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) diff --git a/src/plat/apq8064/machine/hardware.c b/src/plat/apq8064/machine/hardware.c index b3ca15729..6914dccf4 100644 --- a/src/plat/apq8064/machine/hardware.c +++ b/src/plat/apq8064/machine/hardware.c @@ -319,7 +319,7 @@ map_kernel_devices(void) TIMER_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -330,7 +330,7 @@ map_kernel_devices(void) GIC_CONTROLLER_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -340,7 +340,7 @@ map_kernel_devices(void) GIC_DISTRIBUTOR_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -353,7 +353,7 @@ map_kernel_devices(void) UART_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) diff --git a/src/plat/exynos4/machine/hardware.c b/src/plat/exynos4/machine/hardware.c index 619ccba8b..082bda1da 100644 --- a/src/plat/exynos4/machine/hardware.c +++ b/src/plat/exynos4/machine/hardware.c @@ -235,7 +235,7 @@ map_kernel_devices(void) MCT_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -247,7 +247,7 @@ map_kernel_devices(void) GIC_CONTROLLER_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -257,7 +257,7 @@ map_kernel_devices(void) GIC_DISTRIBUTOR_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -269,7 +269,7 @@ map_kernel_devices(void) L2CC_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -282,7 +282,7 @@ map_kernel_devices(void) UART_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) diff --git a/src/plat/exynos5/machine/hardware.c b/src/plat/exynos5/machine/hardware.c index aed3e5184..6fdf5f827 100644 --- a/src/plat/exynos5/machine/hardware.c +++ b/src/plat/exynos5/machine/hardware.c @@ -294,7 +294,7 @@ map_kernel_devices(void) MCT_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -306,7 +306,7 @@ map_kernel_devices(void) GIC_CONTROLLER_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -316,7 +316,7 @@ map_kernel_devices(void) GIC_DISTRIBUTOR_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -329,7 +329,7 @@ map_kernel_devices(void) UART_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) diff --git a/src/plat/imx31/machine/hardware.c b/src/plat/imx31/machine/hardware.c index 339dfc528..3ba502464 100644 --- a/src/plat/imx31/machine/hardware.c +++ b/src/plat/imx31/machine/hardware.c @@ -228,7 +228,7 @@ map_kernel_devices(void) EPIT_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -240,7 +240,7 @@ map_kernel_devices(void) AVIC_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -252,7 +252,7 @@ map_kernel_devices(void) L2CC_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -265,7 +265,7 @@ map_kernel_devices(void) UART_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) diff --git a/src/plat/imx6/machine/hardware.c b/src/plat/imx6/machine/hardware.c index ffeaf23ce..242dde7e1 100644 --- a/src/plat/imx6/machine/hardware.c +++ b/src/plat/imx6/machine/hardware.c @@ -205,7 +205,7 @@ map_kernel_devices(void) ARM_MP_PPTR1, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -217,7 +217,7 @@ map_kernel_devices(void) ARM_MP_PPTR2, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -229,7 +229,7 @@ map_kernel_devices(void) L2CC_PL310_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -243,7 +243,7 @@ map_kernel_devices(void) UART_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) diff --git a/src/plat/omap3/machine/hardware.c b/src/plat/omap3/machine/hardware.c index f62b179cd..50d62cd75 100644 --- a/src/plat/omap3/machine/hardware.c +++ b/src/plat/omap3/machine/hardware.c @@ -178,7 +178,7 @@ map_kernel_devices(void) GPTIMER11_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -190,7 +190,7 @@ map_kernel_devices(void) INTC_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -203,7 +203,7 @@ map_kernel_devices(void) UART3_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) diff --git a/src/plat/zynq7000/machine/hardware.c b/src/plat/zynq7000/machine/hardware.c index 8f414174d..06ad98a2b 100644 --- a/src/plat/zynq7000/machine/hardware.c +++ b/src/plat/zynq7000/machine/hardware.c @@ -137,7 +137,7 @@ map_kernel_devices(void) ARM_MP_PPTR1, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -149,7 +149,7 @@ map_kernel_devices(void) ARM_MP_PPTR2, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -161,7 +161,7 @@ map_kernel_devices(void) L2CC_PL310_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -175,7 +175,7 @@ map_kernel_devices(void) UART_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) From 4f12acd2703183c9f44fe097589b53eb53c599eb Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Thu, 26 Feb 2015 12:25:29 +1100 Subject: [PATCH 03/19] ARM: Map the initial thread's IPC buffer and boot info as non-executable. Note that this also required some irrelevant x86 changes to match function arguments. --- include/arch/arm/arch/kernel/boot.h | 2 +- include/arch/arm/arch/kernel/vspace.h | 2 +- include/arch/ia32/arch/kernel/boot.h | 2 +- src/arch/arm/kernel/boot.c | 4 ++-- src/arch/arm/kernel/vspace.c | 4 ++-- src/arch/ia32/kernel/boot.c | 3 ++- src/kernel/boot.c | 6 +++--- 7 files changed, 12 insertions(+), 11 deletions(-) diff --git a/include/arch/arm/arch/kernel/boot.h b/include/arch/arm/arch/kernel/boot.h index f94ffa9bd..57e26ad4f 100644 --- a/include/arch/arm/arch/kernel/boot.h +++ b/include/arch/arm/arch/kernel/boot.h @@ -14,7 +14,7 @@ #include cap_t create_unmapped_it_frame_cap(pptr_t pptr, bool_t use_large); -cap_t create_mapped_it_frame_cap(cap_t pd_cap, pptr_t pptr, vptr_t vptr, asid_t asid, bool_t use_large); +cap_t create_mapped_it_frame_cap(cap_t pd_cap, pptr_t pptr, vptr_t vptr, asid_t asid, bool_t use_large, bool_t executable); void init_kernel( paddr_t ui_p_reg_start, diff --git a/include/arch/arm/arch/kernel/vspace.h b/include/arch/arm/arch/kernel/vspace.h index 2e6e703e4..b754a53a7 100644 --- a/include/arch/arm/arch/kernel/vspace.h +++ b/include/arch/arm/arch/kernel/vspace.h @@ -18,7 +18,7 @@ #define IT_ASID 1 /* initial thread's ASID */ void map_it_pt_cap(cap_t pd_cap, cap_t pt_cap); -void map_it_frame_cap(cap_t pd_cap, cap_t frame_cap); +void map_it_frame_cap(cap_t pd_cap, cap_t frame_cap, bool_t executable); void map_kernel_window(void); void map_kernel_frame(paddr_t paddr, pptr_t vaddr, vm_rights_t vm_rights, vm_attributes_t vm_attributes); void activate_global_pd(void); diff --git a/include/arch/ia32/arch/kernel/boot.h b/include/arch/ia32/arch/kernel/boot.h index 2e873b69b..79a62d82a 100644 --- a/include/arch/ia32/arch/kernel/boot.h +++ b/include/arch/ia32/arch/kernel/boot.h @@ -26,7 +26,7 @@ typedef struct ui_info { } ui_info_t; cap_t create_unmapped_it_frame_cap(pptr_t pptr, bool_t use_large); -cap_t create_mapped_it_frame_cap(cap_t pd_cap, pptr_t pptr, vptr_t vptr, asid_t asid, bool_t use_large); +cap_t create_mapped_it_frame_cap(cap_t pd_cap, pptr_t pptr, vptr_t vptr, asid_t asid, bool_t use_large, bool_t executable); bool_t init_node_state( p_region_t avail_p_reg, diff --git a/src/arch/arm/kernel/boot.c b/src/arch/arm/kernel/boot.c index 2ca4857d5..656964ca8 100644 --- a/src/arch/arm/kernel/boot.c +++ b/src/arch/arm/kernel/boot.c @@ -169,10 +169,10 @@ create_unmapped_it_frame_cap(pptr_t pptr, bool_t use_large) } BOOT_CODE cap_t -create_mapped_it_frame_cap(cap_t pd_cap, pptr_t pptr, vptr_t vptr, asid_t asid, bool_t use_large) +create_mapped_it_frame_cap(cap_t pd_cap, pptr_t pptr, vptr_t vptr, asid_t asid, bool_t use_large, bool_t executable) { cap_t cap = create_it_frame_cap(pptr, vptr, asid, use_large); - map_it_frame_cap(pd_cap, cap); + map_it_frame_cap(pd_cap, cap, executable); return cap; } diff --git a/src/arch/arm/kernel/vspace.c b/src/arch/arm/kernel/vspace.c index b8d68f2bb..8dddb4d17 100644 --- a/src/arch/arm/kernel/vspace.c +++ b/src/arch/arm/kernel/vspace.c @@ -108,7 +108,7 @@ map_it_pt_cap(cap_t pd_cap, cap_t pt_cap) } BOOT_CODE void -map_it_frame_cap(cap_t pd_cap, cap_t frame_cap) +map_it_frame_cap(cap_t pd_cap, cap_t frame_cap, bool_t executable) { pte_t* pt; pte_t* targetSlot; @@ -131,7 +131,7 @@ map_it_frame_cap(cap_t pd_cap, cap_t frame_cap) APFromVMRights(VMReadWrite), 1, /* cacheable */ 1, /* write-back caching */ - 0 /* executable */ + !executable ); } diff --git a/src/arch/ia32/kernel/boot.c b/src/arch/ia32/kernel/boot.c index 007fa4aa2..2b668b8b2 100644 --- a/src/arch/ia32/kernel/boot.c +++ b/src/arch/ia32/kernel/boot.c @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef CONFIG_IOMMU #include @@ -95,7 +96,7 @@ create_unmapped_it_frame_cap(pptr_t pptr, bool_t use_large) } BOOT_CODE cap_t -create_mapped_it_frame_cap(cap_t vspace_cap, pptr_t pptr, vptr_t vptr, asid_t asid, bool_t use_large) +create_mapped_it_frame_cap(cap_t vspace_cap, pptr_t pptr, vptr_t vptr, asid_t asid, bool_t use_large, bool_t executable UNUSED) { cap_t cap = create_it_frame_cap(pptr, vptr, asid, use_large); map_it_frame_cap(vspace_cap, cap); diff --git a/src/kernel/boot.c b/src/kernel/boot.c index fc702747d..c8816c851 100644 --- a/src/kernel/boot.c +++ b/src/kernel/boot.c @@ -218,7 +218,7 @@ create_ipcbuf_frame(cap_t root_cnode_cap, cap_t pd_cap, vptr_t vptr) clearMemory((void*)pptr, PAGE_BITS); /* create a cap of it and write it into the root CNode */ - cap = create_mapped_it_frame_cap(pd_cap, pptr, vptr, IT_ASID, false); + cap = create_mapped_it_frame_cap(pd_cap, pptr, vptr, IT_ASID, false, false); write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), BI_CAP_IT_IPCBUF), cap); return cap; @@ -235,7 +235,7 @@ create_bi_frame_cap( cap_t cap; /* create a cap of it and write it into the root CNode */ - cap = create_mapped_it_frame_cap(pd_cap, pptr, vptr, IT_ASID, false); + cap = create_mapped_it_frame_cap(pd_cap, pptr, vptr, IT_ASID, false, false); write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), BI_CAP_BI_FRAME), cap); } @@ -300,7 +300,7 @@ create_frames_of_region( for (f = reg.start; f < reg.end; f += BIT(PAGE_BITS)) { if (do_map) { - frame_cap = create_mapped_it_frame_cap(pd_cap, f, f - BASE_OFFSET - pv_offset, IT_ASID, false); + frame_cap = create_mapped_it_frame_cap(pd_cap, f, f - BASE_OFFSET - pv_offset, IT_ASID, false, true); } else { frame_cap = create_unmapped_it_frame_cap(f, false); } From a9111d4b5d06599ef19e570429f5c1a709f5999d Mon Sep 17 00:00:00 2001 From: Adrian Danis Date: Tue, 10 Mar 2015 12:17:55 +1100 Subject: [PATCH 04/19] libsel4: Support multiple struct types for the generated syscall stubs --- .../arch_include/arm/interfaces/sel4arch.xml | 38 +++++++++--------- .../arch_include/ia32/interfaces/sel4arch.xml | 30 +++++++------- libsel4/tools/syscall_stub_gen.py | 39 ++++++++++++------- 3 files changed, 59 insertions(+), 48 deletions(-) diff --git a/libsel4/arch_include/arm/interfaces/sel4arch.xml b/libsel4/arch_include/arm/interfaces/sel4arch.xml index 53fde3f4c..ebb23d752 100644 --- a/libsel4/arch_include/arm/interfaces/sel4arch.xml +++ b/libsel4/arch_include/arm/interfaces/sel4arch.xml @@ -9,25 +9,25 @@ @TAG(NICTA_BSD) --> - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/libsel4/arch_include/ia32/interfaces/sel4arch.xml b/libsel4/arch_include/ia32/interfaces/sel4arch.xml index a4e5510ee..a7f066bc8 100644 --- a/libsel4/arch_include/ia32/interfaces/sel4arch.xml +++ b/libsel4/arch_include/ia32/interfaces/sel4arch.xml @@ -9,21 +9,21 @@ @TAG(NICTA_BSD) --> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/libsel4/tools/syscall_stub_gen.py b/libsel4/tools/syscall_stub_gen.py index d34542a71..944030a2e 100644 --- a/libsel4/tools/syscall_stub_gen.py +++ b/libsel4/tools/syscall_stub_gen.py @@ -234,6 +234,12 @@ arch_types = { ] } +# Retrieve a member list for a given struct type +def struct_members(type, structs): + members = [member for struct_name, member in structs if struct_name == type.name] + assert len(members) == 1 + return members[0] + # Keep increasing the given number 'x' until 'x % a == 0'. def align_up(x, a): if x % a == 0: @@ -286,7 +292,7 @@ def generate_param_list(input_params, output_params): return ", ".join(params) -def generate_marshal_expressions(params, num_mrs, registers): +def generate_marshal_expressions(params, num_mrs, structs): """ Generate marshalling expressions for the given set of inputs. @@ -334,7 +340,7 @@ def generate_marshal_expressions(params, num_mrs, registers): assert target_offset == 0 num_words = num_bits / WORD_SIZE_BITS for i in range(num_words): - expr = param.type.c_expression(param.name, i, registers); + expr = param.type.c_expression(param.name, i, struct_members(param.type, structs)); word_array[target_word + i].append(expr) @@ -436,7 +442,7 @@ def generate_result_struct(interface_name, method_name, output_params): return "\n".join(result) -def generate_stub(arch, interface_name, method_name, method_id, input_params, output_params, registers, use_only_ipc_buffer): +def generate_stub(arch, interface_name, method_name, method_id, input_params, output_params, structs, use_only_ipc_buffer): result = [] if use_only_ipc_buffer: @@ -477,7 +483,7 @@ def generate_stub(arch, interface_name, method_name, method_id, input_params, ou # # Get a list of expressions for our caps and inputs. # - input_expressions = generate_marshal_expressions(standard_params, num_mrs, registers) + input_expressions = generate_marshal_expressions(standard_params, num_mrs, structs) cap_expressions = [x.name for x in cap_params] service_cap = cap_expressions[0] cap_expressions = cap_expressions[1:] @@ -560,8 +566,9 @@ def generate_stub(arch, interface_name, method_name, method_id, input_params, ou unmashalled_params = generate_unmarshal_expressions(output_params) for (param, words) in unmashalled_params: if param.type.pass_by_reference(): + members = struct_members(param.type, structs); for i in range(len(words)): - result.append("\t%s->%s = %s;" % (param.name, registers[i], words[i] % source_words)) + result.append("\t%s->%s = %s;" % (param.name, members[i], words[i] % source_words)) else: if param.type.double_word: result.append("\tresult.%s = ((uint64_t)%s + ((uint64_t)%s << 32));" % (param.name, words[0] % source_words, words[1] % source_words)) @@ -597,12 +604,16 @@ def parse_xml_file(input_file, valid_types): # Parse the XML to generate method structures. methods = [] - registers = [] + structs = [] doc = xml.dom.minidom.parse(input_file) - for register in doc.getElementsByTagName("register"): - register_name = (register.getAttribute("name")).lower() - registers.append(register_name) + for struct in doc.getElementsByTagName("struct"): + struct_members = [] + struct_name = struct.getAttribute("name") + for members in struct.getElementsByTagName("member"): + member_name = members.getAttribute("name") + struct_members.append(member_name) + structs.append( (struct_name, struct_members) ) for interface in doc.getElementsByTagName("interface"): interface_name = interface.getAttribute("name") @@ -630,7 +641,7 @@ def parse_xml_file(input_file, valid_types): output_params.append(Parameter(param_name, param_type)) methods.append((interface_name, method_name, method_id, input_params, output_params)) - return (methods, registers) + return (methods, structs) def generate_stub_file(arch, input_files, output_file, use_only_ipc_buffer): """ @@ -645,11 +656,11 @@ def generate_stub_file(arch, input_files, output_file, use_only_ipc_buffer): # Parse XML methods = [] - registers = [] + structs = [] for file in input_files: - method, register = parse_xml_file(file, types + arch_types[arch]) + method, struct = parse_xml_file(file, types + arch_types[arch]) methods += method - registers += register + structs += struct # Print header. result.append(""" @@ -711,7 +722,7 @@ def generate_stub_file(arch, input_files, output_file, use_only_ipc_buffer): result.append(" */") for (interface_name, method_name, method_id, inputs, outputs) in methods: result.append(generate_stub(arch, interface_name, method_name, - method_id, inputs, outputs, registers, use_only_ipc_buffer)) + method_id, inputs, outputs, structs, use_only_ipc_buffer)) # Print footer. result.append("#endif /* __LIBSEL4_SEL4_CLIENT_H */") From 12990f20922c6fdefc5ee4858674eb45d81418a1 Mon Sep 17 00:00:00 2001 From: Adrian Danis Date: Thu, 12 Mar 2015 16:06:58 +1100 Subject: [PATCH 05/19] libsel4: Updating xml specification for syscall stub changes --- libsel4/tools/sel4_idl.dtd | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libsel4/tools/sel4_idl.dtd b/libsel4/tools/sel4_idl.dtd index 6ac5106aa..54c2ad4ba 100644 --- a/libsel4/tools/sel4_idl.dtd +++ b/libsel4/tools/sel4_idl.dtd @@ -8,12 +8,13 @@ @TAG(NICTA_BSD) --> - + - + + - - + + From de935520cf68bc0da7360d5e9c97f0f405e5afa1 Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Wed, 18 Mar 2015 17:11:27 +1100 Subject: [PATCH 06/19] ARM: Add some debugging error printfs for failed PD lookup during page map. This helps more easily diagnose the case where a lookup failure from a page map is not caused by a failure to lookup the page cap, but a failure to lookup the PD cap. No effect on verification. --- src/arch/arm/kernel/vspace.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/arch/arm/kernel/vspace.c b/src/arch/arm/kernel/vspace.c index 8dddb4d17..d770d92c3 100644 --- a/src/arch/arm/kernel/vspace.c +++ b/src/arch/arm/kernel/vspace.c @@ -1429,6 +1429,7 @@ decodeARMFrameInvocation(word_t label, unsigned int length, find_ret = findPDForASID(asid); if (unlikely(find_ret.status != EXCEPTION_NONE)) { + userError("ARMPageMap: No PD for ASID"); current_syscall_error.type = seL4_FailedLookup; current_syscall_error.failedLookupWasSource = @@ -1548,6 +1549,7 @@ decodeARMFrameInvocation(word_t label, unsigned int length, find_ret = findPDForASID(mappedASID); if (unlikely(find_ret.status != EXCEPTION_NONE)) { + userError("ARMPageRemap: No PD for ASID"); current_syscall_error.type = seL4_FailedLookup; current_syscall_error.failedLookupWasSource = false; From 5ef85de0c1f3e98628e81778d0e6287c73d08101 Mon Sep 17 00:00:00 2001 From: akroh Date: Thu, 19 Mar 2015 12:03:56 +1100 Subject: [PATCH 07/19] Fix user access for VCNT --- src/arch/arm/armv/armv7-a/user_access.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/arch/arm/armv/armv7-a/user_access.c b/src/arch/arm/armv/armv7-a/user_access.c index c198be148..398acf040 100644 --- a/src/arch/arm/armv/armv7-a/user_access.c +++ b/src/arch/arm/armv/armv7-a/user_access.c @@ -43,7 +43,7 @@ check_export_arch_timer(void) v |= CNTKCTL_PL0PCTEN; #endif #ifdef CONFIG_EXPORT_VCNT_USER - v |= CNTKCTL_PL0PCTEN; + v |= CNTKCTL_PL0VCTEN; #endif MCR(CNTKCTL, v); } From 092b2c1f35c3b21850123d8dfb65b0e4853e4600 Mon Sep 17 00:00:00 2001 From: Tim Newsham Date: Sat, 14 Mar 2015 15:36:30 -1000 Subject: [PATCH 08/19] am335x: allow UART to be used even in debug mode --- src/plat/am335x/machine/hardware.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plat/am335x/machine/hardware.c b/src/plat/am335x/machine/hardware.c index f94065481..41a4eb189 100644 --- a/src/plat/am335x/machine/hardware.c +++ b/src/plat/am335x/machine/hardware.c @@ -42,9 +42,7 @@ BOOT_CODE p_region_t get_avail_p_reg(unsigned int i) const p_region_t BOOT_RODATA dev_p_regs[] = { /* SoC devices: */ -#ifndef DEBUG { /* .start = */ UART0_PADDR, /* .end = */ UART0_PADDR + (1 << PAGE_BITS) }, -#endif { /* .start = */ DMTIMER2_PADDR, /* .end = */ DMTIMER2_PADDR + (1 << PAGE_BITS) }, { /* .start = */ DMTIMER3_PADDR, /* .end = */ DMTIMER3_PADDR + (1 << PAGE_BITS) }, { /* .start = */ DMTIMER4_PADDR, /* .end = */ DMTIMER4_PADDR + (1 << PAGE_BITS) }, From a5f61c7166c0f44cdc062b8599009a90f29e124d Mon Sep 17 00:00:00 2001 From: akroh Date: Mon, 23 Mar 2015 10:34:08 +1100 Subject: [PATCH 09/19] ARM: Fix hardcoded CPSR value for the idle thread --- include/arch/arm/arch/machine/registerset.h | 4 ++++ src/arch/arm/kernel/thread.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/arch/arm/arch/machine/registerset.h b/include/arch/arm/arch/machine/registerset.h index 21bc11418..3c5103b2d 100644 --- a/include/arch/arm/arch/machine/registerset.h +++ b/include/arch/arm/arch/machine/registerset.h @@ -33,6 +33,10 @@ | PMODE_SUPERVISOR \ | CPSR_EXTRA_FLAGS ) +#define CPSR_IDLETHREAD ( PMASK_FIRQ \ + | PMODE_SUPERVISOR \ + | CPSR_EXTRA_FLAGS ) + #ifdef __ASSEMBLER__ /* Offsets within the user context, these need to match the order in diff --git a/src/arch/arm/kernel/thread.c b/src/arch/arm/kernel/thread.c index ee88fce2e..a9af57799 100644 --- a/src/arch/arm/kernel/thread.c +++ b/src/arch/arm/kernel/thread.c @@ -26,7 +26,7 @@ Arch_switchToThread(tcb_t *tcb) BOOT_CODE void Arch_configureIdleThread(tcb_t *tcb) { - setRegister(tcb, CPSR, 0x1f); + setRegister(tcb, CPSR, CPSR_IDLETHREAD); setRegister(tcb, LR_svc, (word_t)idleThreadStart); } From 60ed6810956e54c62e70fc49f4de9bb59f1acd6e Mon Sep 17 00:00:00 2001 From: Gerwin Klein Date: Wed, 1 Apr 2015 11:47:42 +1100 Subject: [PATCH 10/19] CONTRIBUTING.md file for github --- CONTRIBUTING.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..59b81a89d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,40 @@ +Contributions to the seL4 kernel repository are welcome! + + +## CLA + +Please note that GD and NICTA require a contributor license agreement (CLA) +to be signed for all external contributions. Please see +https://seL4.systems/Contributing for details (it is a fairly short and +standard CLA). + +For the `seL4/seL4` repository, we can review pull requests directly on +github if we have a signed CLA on file. + +If you have only small trivial changes such as style, typos, comments, or +white space and don't want to sign a CLA for that, please file an issue in +the github issue tracker, we'll usually be happy to do the change ourselves +and attribute your idea by linking to the github issue in the change set +comment. + + +## Kernel Development Process + +Please read https://seL4.systems/Contributing + + +## Build/Test + +Generally, any contributions should pass the tests in the project +https://github.com/seL4/sel4test. If new features or platforms are added, +they should add corresponding tests in `sel4test`. + +Contributions to `master` should additionally either be invisible to the +proof in https://github.com/seL4/l4v, such as comments, documentation, style, +unverified platform, etc, or they should come with proof updates to `l4v`. + + +## Contact + +If you have larger changes or additions, it might be a good idea to get in +contact with us as , so we can help you get started. From 5ddff6cf22234fcf4fbeb51d2040728e2004fb3d Mon Sep 17 00:00:00 2001 From: Gerwin Klein Date: Wed, 1 Apr 2015 11:58:31 +1100 Subject: [PATCH 11/19] add Tim Newsham and Robbie Van Vossen to contributor list --- CONTRIBUTORS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 5c1799ba9..5baa8f865 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -40,6 +40,7 @@ repository (in alphabetical order). * Anna Lyons, NICTA & UNSW * Stephanie McArthur, NICTA * Sam McNally, NICTA +* Tim Newsham * Toby Murray, NICTA & UNSW * Ameya Palande, NICTA * Max R.D. Parmer @@ -48,6 +49,7 @@ repository (in alphabetical order). * Sean Seefried, NICTA * Thomas Sewell, NICTA & UNSW * Michael von Tessin, NICTA & UNSW +* Robbie Van Vossen * Adam Walker, NICTA * James Wilmot, NICTA * Simon Winwood, NICTA From efcacb55ba71ffe932675739308f2501d8fc34ee Mon Sep 17 00:00:00 2001 From: Sean Peters Date: Wed, 15 Apr 2015 11:56:31 +1000 Subject: [PATCH 12/19] split the types header into basic and compound to resolve circular dependencies --- include/basic_types.h | 41 ++++++++++++++++++++++++++++++++++++++++ include/compound_types.h | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 include/basic_types.h create mode 100644 include/compound_types.h diff --git a/include/basic_types.h b/include/basic_types.h new file mode 100644 index 000000000..914061520 --- /dev/null +++ b/include/basic_types.h @@ -0,0 +1,41 @@ +/* + * Copyright 2014, General Dynamics C4 Systems + * + * This software may be distributed and modified according to the terms of + * the GNU General Public License version 2. Note that NO WARRANTY is provided. + * See "LICENSE_GPLv2.txt" for details. + * + * @TAG(GD_GPL) + */ + +#ifndef __BASIC_TYPES_H +#define __BASIC_TYPES_H + +#include +#include + +enum _bool { + false = 0, + true = 1 +}; +typedef uint32_t bool_t; + +typedef struct region { + pptr_t start; + pptr_t end; +} region_t; + +typedef struct p_region { + paddr_t start; + paddr_t end; +} p_region_t; + +typedef struct v_region { + vptr_t start; + vptr_t end; +} v_region_t; + +#define REG_EMPTY (region_t){ .start = 0, .end = 0 } +#define P_REG_EMPTY (p_region_t){ .start = 0, .end = 0 } + +#endif /* __BASIC_TYPES_H */ diff --git a/include/compound_types.h b/include/compound_types.h new file mode 100644 index 000000000..fdd172154 --- /dev/null +++ b/include/compound_types.h @@ -0,0 +1,38 @@ +/* + * Copyright 2014, General Dynamics C4 Systems + * + * This software may be distributed and modified according to the terms of + * the GNU General Public License version 2. Note that NO WARRANTY is provided. + * See "LICENSE_GPLv2.txt" for details. + * + * @TAG(GD_GPL) + */ + +#ifndef __COMPOUND_TYPES_H +#define __COMPOUND_TYPES_H + +#include +#include +#include +#include + +struct pde_range { + pde_t *base; + unsigned int length; +}; +typedef struct pde_range pde_range_t; + +struct pte_range { + pte_t *base; + unsigned int length; +}; +typedef struct pte_range pte_range_t; + +typedef cte_t *cte_ptr_t; + +struct extra_caps { + cte_ptr_t excaprefs[seL4_MsgMaxExtraCaps]; +}; +typedef struct extra_caps extra_caps_t; + +#endif /* __COMPOUND_TYPES_H */ From 8abdf6c5ed5f37540cdbe28fcb5818dce1529c43 Mon Sep 17 00:00:00 2001 From: Sean Peters Date: Wed, 15 Apr 2015 11:56:44 +1000 Subject: [PATCH 13/19] ia32: added the option to disable prefetchers --- Kconfig | 9 +++++ include/arch/ia32/arch/machine.h | 24 +++++++++++ include/arch/ia32/arch/machine/hardware.h | 4 ++ include/types.h | 49 +---------------------- include/util.h | 1 + src/arch/ia32/kernel/boot.c | 6 +++ src/arch/ia32/machine/hardware.c | 34 ++++++++++++++++ src/arch/ia32/machine_asm.S | 9 +++++ 8 files changed, 89 insertions(+), 47 deletions(-) diff --git a/Kconfig b/Kconfig index a1cdb320f..922c96777 100644 --- a/Kconfig +++ b/Kconfig @@ -374,6 +374,15 @@ menu "Build Options" expense of dramatically decreasing performance. Primary use is for debugging. + config DEBUG_DISABLE_PREFETCHERS + bool "Disable prefetchers" + depends on ARCH_IA32 + default n + help + On ia32 platforms, this option disables the L2 hardware prefetcher, the L2 + adjacent cache line prefetcher, the DCU prefetcher and the DCU IP prefetcher. + Currently unimplemented on other platforms. + endmenu menu "Errata" diff --git a/include/arch/ia32/arch/machine.h b/include/arch/ia32/arch/machine.h index a033bc046..51ec1fcfa 100644 --- a/include/arch/ia32/arch/machine.h +++ b/include/arch/ia32/arch/machine.h @@ -25,6 +25,29 @@ #define IA32_SYSENTER_ESP_MSR 0x175 #define IA32_SYSENTER_EIP_MSR 0x176 +#define BROADWELL_MODEL_ID 0xD4 +#define HASWELL_MODEL_ID 0xC3 +#define IVY_BRIDGE_MODEL_ID 0xA9 +#define SANDY_BRIDGE_1_MODEL_ID 0x2A /* Sandy Bridge */ +#define SANDY_BRIDGE_2_MODEL_ID 0x2D /* Sandy Bridge-E, Sandy Bridge-EN and Sandy Bridge-EP */ +#define WESTMERE_1_MODEL_ID 0x25 /* Arrandale and Clarksdale */ +#define WESTMERE_2_MODEL_ID 0x2C /* Gulftown and Westmere-EP */ +#define WESTMERE_3_MODEL_ID 0x2F /* Westemere-EX */ +#define NEHALEM_1_MODEL_ID 0x1E /* Clarksfield, Lynnfield and Jasper Forest */ +#define NEHALEM_2_MODEL_ID 0x1A /* Bloomfield and Nehalem-EP */ +#define NEHALEM_3_MODEL_ID 0x2E /* Nehalem-EX */ + +#define MODEL_ID(x) ( ((x & 0xf0000) >> 16) + (x & 0xf0) ) + +/* This article discloses prefetcher control on Intel processors; Nehalem, Westmere, Sandy Bridge, + Ivy Bridge, Haswell, and Broadwell. It is currently undocumented in the regular intel manuals. + https://software.intel.com/en-us/articles/disclosure-of-hw-prefetcher-control-on-some-intel-processors */ +#define IA32_PREFETCHER_MSR 0x1A4 +#define IA32_PREFETCHER_MSR_L2 BIT(0) +#define IA32_PREFETCHER_MSR_L2_ADJACENT BIT(1) +#define IA32_PREFETCHER_MSR_DCU BIT(2) +#define IA32_PREFETCHER_MSR_DCU_IP BIT(3) + word_t PURE getRestartPC(tcb_t *thread); void setNextPC(tcb_t *thread, word_t v); @@ -87,6 +110,7 @@ void ia32_wrmsr(const uint32_t reg, const uint32_t val_high, const uint32_t val_ /* Read different parts of CPUID */ uint32_t ia32_cpuid_edx(uint32_t eax, uint32_t ecx); +uint32_t ia32_cpuid_eax(uint32_t eax, uint32_t ecx); /* Read/write memory fence */ void ia32_mfence(void); diff --git a/include/arch/ia32/arch/machine/hardware.h b/include/arch/ia32/arch/machine/hardware.h index 190d5195c..60ec65db9 100644 --- a/include/arch/ia32/arch/machine/hardware.h +++ b/include/arch/ia32/arch/machine/hardware.h @@ -11,6 +11,7 @@ #ifndef __ARCH_MACHINE_HARDWARE_H #define __ARCH_MACHINE_HARDWARE_H +#include #include #include #include @@ -87,4 +88,7 @@ uint32_t CONST getCacheLineSizeBits(void); void flushCacheLine(void* vaddr); void flushCacheRange(void* vaddr, uint32_t size_bits); +/* Disables a variety of prefetchers */ +bool_t disablePrefetchers(void); + #endif diff --git a/include/types.h b/include/types.h index 9c9219b98..28ae3817c 100644 --- a/include/types.h +++ b/include/types.h @@ -11,52 +11,7 @@ #ifndef __TYPES_H #define __TYPES_H -#include -#include -#include -#include - -enum _bool { - false = 0, - true = 1 -}; -typedef uint32_t bool_t; - -typedef struct region { - pptr_t start; - pptr_t end; -} region_t; - -typedef struct p_region { - paddr_t start; - paddr_t end; -} p_region_t; - -typedef struct v_region { - vptr_t start; - vptr_t end; -} v_region_t; - -#define REG_EMPTY (region_t){ .start = 0, .end = 0 } -#define P_REG_EMPTY (p_region_t){ .start = 0, .end = 0 } - -struct pde_range { - pde_t *base; - unsigned int length; -}; -typedef struct pde_range pde_range_t; - -struct pte_range { - pte_t *base; - unsigned int length; -}; -typedef struct pte_range pte_range_t; - -typedef cte_t *cte_ptr_t; - -struct extra_caps { - cte_ptr_t excaprefs[seL4_MsgMaxExtraCaps]; -}; -typedef struct extra_caps extra_caps_t; +#include +#include #endif diff --git a/include/util.h b/include/util.h index 9f5ce18cc..52fd9540f 100644 --- a/include/util.h +++ b/include/util.h @@ -17,6 +17,7 @@ #define ROUND_UP(n, b) (((((n) - 1ul) >> (b)) + 1ul) << (b)) #define CTZ(x) __builtin_ctz(x) #define CLZ(x) __builtin_clz(x) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #ifndef __ASSEMBLER__ diff --git a/src/arch/ia32/kernel/boot.c b/src/arch/ia32/kernel/boot.c index 2b668b8b2..b9ead9a1c 100644 --- a/src/arch/ia32/kernel/boot.c +++ b/src/arch/ia32/kernel/boot.c @@ -575,6 +575,12 @@ init_node_cpu( if (!apic_init(apic_khz, mask_legacy_irqs)) { return false; } + +#ifdef CONFIG_DEBUG_DISABLE_PREFETCHERS + if (!disablePrefetchers()) { + return false; + } +#endif return true; } diff --git a/src/arch/ia32/machine/hardware.c b/src/arch/ia32/machine/hardware.c index 4eab96686..1f903bcae 100644 --- a/src/arch/ia32/machine/hardware.c +++ b/src/arch/ia32/machine/hardware.c @@ -82,3 +82,37 @@ void flushCacheRange(void* vaddr, uint32_t size_bits) } ia32_mfence(); } + +/* Disables as many prefetchers as possible */ +BOOT_CODE bool_t +disablePrefetchers() +{ + uint32_t version_info; + uint32_t low, high; + int i; + + uint32_t valid_models[] = { BROADWELL_MODEL_ID, HASWELL_MODEL_ID, IVY_BRIDGE_MODEL_ID, + SANDY_BRIDGE_1_MODEL_ID, SANDY_BRIDGE_2_MODEL_ID, WESTMERE_1_MODEL_ID, WESTMERE_2_MODEL_ID, + WESTMERE_3_MODEL_ID, NEHALEM_1_MODEL_ID, NEHALEM_2_MODEL_ID, NEHALEM_3_MODEL_ID }; + + version_info = ia32_cpuid_eax(0x1, 0x0); + + for (i = 0; i < ARRAY_SIZE(valid_models); ++i) { + if (MODEL_ID(version_info) == valid_models[i]) { + low = ia32_rdmsr_low(IA32_PREFETCHER_MSR); + high = ia32_rdmsr_high(IA32_PREFETCHER_MSR); + + low |= IA32_PREFETCHER_MSR_L2; + low |= IA32_PREFETCHER_MSR_L2_ADJACENT; + low |= IA32_PREFETCHER_MSR_DCU; + low |= IA32_PREFETCHER_MSR_DCU_IP; + + ia32_wrmsr(IA32_PREFETCHER_MSR, high, low); + + return true; + } + } + + printf("Disabling prefetchers not implemented for CPU model: %x\n", MODEL_ID(version_info)); + return false; +} diff --git a/src/arch/ia32/machine_asm.S b/src/arch/ia32/machine_asm.S index 703eceec1..4b3436a3b 100644 --- a/src/arch/ia32/machine_asm.S +++ b/src/arch/ia32/machine_asm.S @@ -117,6 +117,15 @@ BEGIN_FUNC(ia32_cpuid_edx) ret END_FUNC(ia32_cpuid_edx) +BEGIN_FUNC(ia32_cpuid_eax) + movl 4(%esp), %eax + movl 8(%esp), %ecx + pushl %ebx + cpuid + popl %ebx + ret +END_FUNC(ia32_cpuid_eax) + .section .text BEGIN_FUNC(invalidateTLB) From e581882c3c2ac67152fcdb3efe4e9c91042cafb7 Mon Sep 17 00:00:00 2001 From: Adrian Danis Date: Fri, 17 Apr 2015 13:52:37 +1000 Subject: [PATCH 14/19] trivial: style --- include/arch/ia32/arch/machine.h | 2 +- src/arch/ia32/kernel/boot.c | 2 +- src/arch/ia32/machine/hardware.c | 11 ++++++----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/arch/ia32/arch/machine.h b/include/arch/ia32/arch/machine.h index 51ec1fcfa..ce9c22efb 100644 --- a/include/arch/ia32/arch/machine.h +++ b/include/arch/ia32/arch/machine.h @@ -39,7 +39,7 @@ #define MODEL_ID(x) ( ((x & 0xf0000) >> 16) + (x & 0xf0) ) -/* This article discloses prefetcher control on Intel processors; Nehalem, Westmere, Sandy Bridge, +/* This article discloses prefetcher control on Intel processors; Nehalem, Westmere, Sandy Bridge, Ivy Bridge, Haswell, and Broadwell. It is currently undocumented in the regular intel manuals. https://software.intel.com/en-us/articles/disclosure-of-hw-prefetcher-control-on-some-intel-processors */ #define IA32_PREFETCHER_MSR 0x1A4 diff --git a/src/arch/ia32/kernel/boot.c b/src/arch/ia32/kernel/boot.c index b9ead9a1c..5a0a83d6d 100644 --- a/src/arch/ia32/kernel/boot.c +++ b/src/arch/ia32/kernel/boot.c @@ -575,7 +575,7 @@ init_node_cpu( if (!apic_init(apic_khz, mask_legacy_irqs)) { return false; } - + #ifdef CONFIG_DEBUG_DISABLE_PREFETCHERS if (!disablePrefetchers()) { return false; diff --git a/src/arch/ia32/machine/hardware.c b/src/arch/ia32/machine/hardware.c index 1f903bcae..42dfedce2 100644 --- a/src/arch/ia32/machine/hardware.c +++ b/src/arch/ia32/machine/hardware.c @@ -84,16 +84,17 @@ void flushCacheRange(void* vaddr, uint32_t size_bits) } /* Disables as many prefetchers as possible */ -BOOT_CODE bool_t +BOOT_CODE bool_t disablePrefetchers() { uint32_t version_info; - uint32_t low, high; + uint32_t low, high; int i; - uint32_t valid_models[] = { BROADWELL_MODEL_ID, HASWELL_MODEL_ID, IVY_BRIDGE_MODEL_ID, - SANDY_BRIDGE_1_MODEL_ID, SANDY_BRIDGE_2_MODEL_ID, WESTMERE_1_MODEL_ID, WESTMERE_2_MODEL_ID, - WESTMERE_3_MODEL_ID, NEHALEM_1_MODEL_ID, NEHALEM_2_MODEL_ID, NEHALEM_3_MODEL_ID }; + uint32_t valid_models[] = { BROADWELL_MODEL_ID, HASWELL_MODEL_ID, IVY_BRIDGE_MODEL_ID, + SANDY_BRIDGE_1_MODEL_ID, SANDY_BRIDGE_2_MODEL_ID, WESTMERE_1_MODEL_ID, WESTMERE_2_MODEL_ID, + WESTMERE_3_MODEL_ID, NEHALEM_1_MODEL_ID, NEHALEM_2_MODEL_ID, NEHALEM_3_MODEL_ID + }; version_info = ia32_cpuid_eax(0x1, 0x0); From 7bd0da5533f3c4fd0746d533a7168f1f0d51f497 Mon Sep 17 00:00:00 2001 From: Tim Newsham Date: Sun, 15 Mar 2015 21:07:37 -1000 Subject: [PATCH 15/19] am335x: setup clock and enable dmtimer3 --- include/plat/am335x/plat/machine/devices.h | 8 ++-- src/plat/am335x/machine/hardware.c | 46 +++++++++++++++++++++- 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/include/plat/am335x/plat/machine/devices.h b/include/plat/am335x/plat/machine/devices.h index adbe8758b..8c9704ecd 100644 --- a/include/plat/am335x/plat/machine/devices.h +++ b/include/plat/am335x/plat/machine/devices.h @@ -16,11 +16,12 @@ #define UART0_PPTR 0xfff02000 #define DMTIMER0_PPTR 0xfff03000 #define WDT1_PPTR 0xfff04000 +#define CMPER_PPTR 0xfff05000 /* Other devices on the SoC. */ -#define INTC_PADDR 0x48200000 -#define UART0_PADDR 0x44E09000 +#define INTC_PADDR 0x48200000 +#define UART0_PADDR 0x44E09000 #define DMTIMER0_PADDR 0x44E05000 #define DMTIMER2_PADDR 0x48040000 #define DMTIMER3_PADDR 0x48042000 @@ -28,7 +29,8 @@ #define DMTIMER5_PADDR 0x48046000 #define DMTIMER6_PADDR 0x48048000 #define DMTIMER7_PADDR 0x4804A000 -#define WDT1_PADDR 0x44e35000 +#define WDT1_PADDR 0x44e35000 +#define CMPER_PADDR 0x44e00000 #endif diff --git a/src/plat/am335x/machine/hardware.c b/src/plat/am335x/machine/hardware.c index 41a4eb189..005d2df62 100644 --- a/src/plat/am335x/machine/hardware.c +++ b/src/plat/am335x/machine/hardware.c @@ -42,14 +42,15 @@ BOOT_CODE p_region_t get_avail_p_reg(unsigned int i) const p_region_t BOOT_RODATA dev_p_regs[] = { /* SoC devices: */ - { /* .start = */ UART0_PADDR, /* .end = */ UART0_PADDR + (1 << PAGE_BITS) }, + { /* .start = */ UART0_PADDR, /* .end = */ UART0_PADDR + (1 << PAGE_BITS) }, { /* .start = */ DMTIMER2_PADDR, /* .end = */ DMTIMER2_PADDR + (1 << PAGE_BITS) }, { /* .start = */ DMTIMER3_PADDR, /* .end = */ DMTIMER3_PADDR + (1 << PAGE_BITS) }, { /* .start = */ DMTIMER4_PADDR, /* .end = */ DMTIMER4_PADDR + (1 << PAGE_BITS) }, { /* .start = */ DMTIMER5_PADDR, /* .end = */ DMTIMER5_PADDR + (1 << PAGE_BITS) }, { /* .start = */ DMTIMER6_PADDR, /* .end = */ DMTIMER6_PADDR + (1 << PAGE_BITS) }, { /* .start = */ DMTIMER7_PADDR, /* .end = */ DMTIMER7_PADDR + (1 << PAGE_BITS) }, - { /* .start = */ WDT1_PADDR, /* .end = */ WDT1_PADDR + (1 << PAGE_BITS) }, + { /* .start = */ WDT1_PADDR, /* .end = */ WDT1_PADDR + (1 << PAGE_BITS) }, + { /* .start = */ CMPER_PADDR, /* .end = */ CMPER_PADDR + (1 << PAGE_BITS) }, /* Board devices. */ /* TODO: This should ultimately be replaced with a more general solution. */ }; @@ -104,6 +105,18 @@ map_kernel_devices(void) ) ); + /* map kernel device: CMPER */ + map_kernel_frame( + CMPER_PADDR, + CMPER_PPTR, + VMKernelOnly, + vm_attributes_new( + true, /* armExecuteNever */ + false, /* armParityEnabled */ + false /* armPageCacheable */ + ) + ); + #ifdef DEBUG /* map kernel device: UART */ map_kernel_frame( @@ -119,6 +132,13 @@ map_kernel_devices(void) #endif } +#define CMPER_REG(base, off) ((volatile uint32_t *)((base) + (off))) +#define CMPER_TIMER3_CLKCTRL 0x84 +#define CMPER_CLKCTRL_DISABLE 0 +#define CMPER_CLKCTRL_ENABLE 2 +#define CMPER_CLKSEL_TIMER3 0x50c +#define CMPER_CKLSEL_MOSC 1 + #define INTCPS_SYSCONFIG_SOFTRESET BIT(1) #define INTCPS_SYSSTATUS_RESETDONE BIT(0) @@ -295,6 +315,27 @@ disableWatchdog(void) } } +/* + * Enable DMTIMER clocks, otherwise their registers wont be accessible. + * This could be moved out of kernel. + */ +static BOOT_CODE void +enableTimers(void) +{ + uint32_t cmper = CMPER_PPTR; + + /* XXX repeat this for DMTIMER4..7 */ + /* select clock */ + *CMPER_REG(cmper, CMPER_CLKSEL_TIMER3) = CMPER_CKLSEL_MOSC; + while((*CMPER_REG(cmper, CMPER_CLKSEL_TIMER3) & 3) != CMPER_CKLSEL_MOSC) + continue; + + /* enable clock */ + *CMPER_REG(cmper, CMPER_TIMER3_CLKCTRL) = CMPER_CLKCTRL_ENABLE; + while((*CMPER_REG(cmper, CMPER_TIMER3_CLKCTRL) & 3) != CMPER_CLKCTRL_ENABLE) + continue; +} + /* Configure dmtimer0 as kernel preemption timer */ /** DONT_TRANSLATE @@ -305,6 +346,7 @@ initTimer(void) int timeout; disableWatchdog(); + enableTimers(); timer->cfg = TIOCP_CFG_SOFTRESET; From 69f37863aa65a285f8d8e8f893c44a5c4156857d Mon Sep 17 00:00:00 2001 From: Adrian Danis Date: Mon, 4 May 2015 11:50:48 +1000 Subject: [PATCH 16/19] Trivial: style --- src/plat/am335x/machine/hardware.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plat/am335x/machine/hardware.c b/src/plat/am335x/machine/hardware.c index 005d2df62..795fb8df5 100644 --- a/src/plat/am335x/machine/hardware.c +++ b/src/plat/am335x/machine/hardware.c @@ -327,15 +327,17 @@ enableTimers(void) /* XXX repeat this for DMTIMER4..7 */ /* select clock */ *CMPER_REG(cmper, CMPER_CLKSEL_TIMER3) = CMPER_CKLSEL_MOSC; - while((*CMPER_REG(cmper, CMPER_CLKSEL_TIMER3) & 3) != CMPER_CKLSEL_MOSC) + while ((*CMPER_REG(cmper, CMPER_CLKSEL_TIMER3) & 3) != CMPER_CKLSEL_MOSC) { continue; + } /* enable clock */ *CMPER_REG(cmper, CMPER_TIMER3_CLKCTRL) = CMPER_CLKCTRL_ENABLE; - while((*CMPER_REG(cmper, CMPER_TIMER3_CLKCTRL) & 3) != CMPER_CLKCTRL_ENABLE) + while ((*CMPER_REG(cmper, CMPER_TIMER3_CLKCTRL) & 3) != CMPER_CLKCTRL_ENABLE) { continue; + } } - + /* Configure dmtimer0 as kernel preemption timer */ /** DONT_TRANSLATE From 1a568e764ab4bae6395b42a7f3edfa320c617a27 Mon Sep 17 00:00:00 2001 From: Gerwin Klein Date: Sat, 9 May 2015 06:46:31 +1000 Subject: [PATCH 17/19] remove generated adglobs type It's become obsolete after correspongin Isabelle C parser change. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f1c9179a8..8d2e18af2 100644 --- a/Makefile +++ b/Makefile @@ -539,7 +539,7 @@ PRUNES = $(foreach file,${STATICSOURCES} ${STATICHEADERS}, \ --prune ${file} ) TOPLEVELTYPES=cte_C tcb_C endpoint_C async_endpoint_C asid_pool_C pte_C \ - pde_C adglobs_struct user_data_C + pde_C user_data_C TOPTYPES = $(foreach tp,${TOPLEVELTYPES}, \ --toplevel ${tp} ) From fc1e413e5b3a23465cf8eca90d3a053650a1c75f Mon Sep 17 00:00:00 2001 From: Adrian Danis Date: Tue, 12 May 2015 17:10:19 +1000 Subject: [PATCH 18/19] ia32: Move many assembly operations from .S file into inline assembly --- include/arch/ia32/arch/machine.h | 92 ++++++++++-- .../arch/ia32/arch/machine/cpu_registers.h | 20 ++- include/arch/ia32/arch/machine/fpu.h | 15 +- include/arch/ia32/arch/machine/hardware.h | 6 +- include/plat/pc99/plat/machine/io.h | 15 +- src/arch/ia32/machine_asm.S | 135 ------------------ 6 files changed, 128 insertions(+), 155 deletions(-) diff --git a/include/arch/ia32/arch/machine.h b/include/arch/ia32/arch/machine.h index ce9c22efb..eba9f5f70 100644 --- a/include/arch/ia32/arch/machine.h +++ b/include/arch/ia32/arch/machine.h @@ -64,14 +64,29 @@ static inline void setCurrentPD(paddr_t addr) } /* TLB control */ -void invalidateTLB(void); -void invalidateTLBentry(vptr_t vptr); +static inline void invalidateTLB(void) +{ + /* rewrite the current page directory */ + write_cr3(ia32KSCurrentPD); +} + +static inline void invalidateTLBentry(vptr_t vptr) +{ + asm volatile("invlpg (%[vptr])" :: [vptr] "r"(vptr)); +} /* Invalidates page structures cache */ -void invalidatePageStructureCache(void); +static inline void invalidatePageStructureCache(void) +{ + /* invalidate an arbitrary line to invalidate the page structure cache */ + invalidateTLBentry(0); +} /* Flushes entire CPU Cache */ -void ia32_wbinvd(void); +static inline void ia32_wbinvd(void) +{ + asm volatile("wbinvd" ::: "memory"); +} /* GDT installation */ void ia32_install_gdt(gdt_idt_ptr_t* gdt_idt_ptr); @@ -86,10 +101,19 @@ void ia32_install_ldt(uint32_t ldt_sel); void ia32_install_tss(uint32_t tss_sel); /* Get page fault address from CR2 register */ -uint32_t getFaultAddr(void); +static inline uint32_t getFaultAddr(void) +{ + return read_cr2(); +} /* Get current stack pointer */ -void* get_current_esp(void); +static inline void* get_current_esp(void) +{ + uint32_t stack; + void *result; + asm volatile("movl %[stack_address], %[result]" : [result] "=r"(result) : [stack_address] "r"(&stack)); + return result; +} /* Cleaning memory before user-level access */ static inline void clearMemory(void* ptr, unsigned int bits) @@ -101,19 +125,63 @@ static inline void clearMemory(void* ptr, unsigned int bits) /* Initialises MSRs required to setup sysenter and sysexit */ void init_sysenter_msrs(void); +static uint64_t ia32_rdmsr(const uint32_t reg) +{ + uint64_t value; + asm volatile("rdmsr" : "=A"(value) : "c"(reg)); + return value; +} + /* Read model specific register */ -uint32_t ia32_rdmsr_low(const uint32_t reg); -uint32_t ia32_rdmsr_high(const uint32_t reg); +static inline uint32_t ia32_rdmsr_low(const uint32_t reg) +{ + return (uint32_t)ia32_rdmsr(reg); +} + +static inline uint32_t ia32_rdmsr_high(const uint32_t reg) +{ + return (uint32_t)(ia32_rdmsr(reg) >> 32ull); +} /* Write model specific register */ -void ia32_wrmsr(const uint32_t reg, const uint32_t val_high, const uint32_t val_low); +static inline void ia32_wrmsr(const uint32_t reg, const uint32_t val_high, const uint32_t val_low) +{ + uint64_t val = ((uint64_t)val_high << 32ull) | (uint64_t)val_low; + asm volatile("wrmsr" :: "A"(val), "c"(reg)); +} /* Read different parts of CPUID */ -uint32_t ia32_cpuid_edx(uint32_t eax, uint32_t ecx); -uint32_t ia32_cpuid_eax(uint32_t eax, uint32_t ecx); +static inline uint32_t ia32_cpuid_edx(uint32_t eax, uint32_t ecx) +{ + uint32_t edx, ebx; + asm volatile("cpuid" + : "=a" (eax), + "=b" (ebx), + "=c" (ecx), + "=d" (edx) + : "a" (eax), "c" (ecx) + : "memory"); + return edx; +} + +static inline uint32_t ia32_cpuid_eax(uint32_t eax, uint32_t ecx) +{ + uint32_t edx, ebx; + asm volatile("cpuid" + : "=a" (eax), + "=b" (ebx), + "=c" (ecx), + "=d" (edx) + : "a" (eax), "c" (ecx) + : "memory"); + return eax; +} /* Read/write memory fence */ -void ia32_mfence(void); +static inline void ia32_mfence(void) +{ + asm volatile("mfence" ::: "memory"); +} /* sysenter entry point */ void handle_syscall(void); diff --git a/include/arch/ia32/arch/machine/cpu_registers.h b/include/arch/ia32/arch/machine/cpu_registers.h index 582fbfab8..4e9338e70 100644 --- a/include/arch/ia32/arch/machine/cpu_registers.h +++ b/include/arch/ia32/arch/machine/cpu_registers.h @@ -47,7 +47,23 @@ static inline void write_cr0(uint32_t val) asm volatile("movl %0, %%cr0" :: "r"(val), "m"(__control_reg_order)); } -uint32_t read_cr4(void); -void write_cr4(uint32_t value); +static inline uint32_t read_cr2(void) +{ + uint32_t val; + asm volatile("movl %%cr2, %0" : "=r"(val), "=m"(__control_reg_order)); + return val; +} + +static inline uint32_t read_cr4(void) +{ + uint32_t val; + asm volatile("movl %%cr4, %0" : "=r"(val), "=m"(__control_reg_order)); + return val; +} + +static inline void write_cr4(uint32_t value) +{ + asm volatile("movl %0, %%cr4" :: "r"(value), "m"(__control_reg_order)); +} #endif diff --git a/include/arch/ia32/arch/machine/fpu.h b/include/arch/ia32/arch/machine/fpu.h index ff4d38715..478be4d28 100644 --- a/include/arch/ia32/arch/machine/fpu.h +++ b/include/arch/ia32/arch/machine/fpu.h @@ -28,13 +28,22 @@ void Arch_fpuThreadDelete(tcb_t *thread); exception_t handleUnimplementedDevice(void); /* Store state in the FPU registers into memory. */ -void saveFpuState(user_fpu_state_t *dest); +static inline void saveFpuState(user_fpu_state_t *dest) +{ + asm volatile("fxsave %[dest]" : [dest] "=m"(*dest)); +} /* Load FPU state from memory into the FPU registers. */ -void loadFpuState(user_fpu_state_t *src); +static inline void loadFpuState(user_fpu_state_t *src) +{ + asm volatile("fxrstor %[src]" :: [src] "m"(*src)); +} /* Reset the FPU registers into their initial blank state. */ -void resetFpu(void); +static inline void resetFpu(void) +{ + asm volatile("finit" :: "m"(__control_reg_order)); +} /* * Enable the FPU to be used without faulting. diff --git a/include/arch/ia32/arch/machine/hardware.h b/include/arch/ia32/arch/machine/hardware.h index 60ec65db9..84a3e70e1 100644 --- a/include/arch/ia32/arch/machine/hardware.h +++ b/include/arch/ia32/arch/machine/hardware.h @@ -85,7 +85,11 @@ uint32_t CONST getCacheLineSize(void); uint32_t CONST getCacheLineSizeBits(void); /* Flushes a specific memory range from the CPU cache */ -void flushCacheLine(void* vaddr); +static inline void flushCacheLine(void* vaddr) +{ + asm volatile("clflush %[vaddr]" :: [vaddr] "m"(vaddr)); +} + void flushCacheRange(void* vaddr, uint32_t size_bits); /* Disables a variety of prefetchers */ diff --git a/include/plat/pc99/plat/machine/io.h b/include/plat/pc99/plat/machine/io.h index 0044aec3e..d9632f234 100644 --- a/include/plat/pc99/plat/machine/io.h +++ b/include/plat/pc99/plat/machine/io.h @@ -21,8 +21,19 @@ uint16_t in16(uint16_t port); uint32_t in32(uint16_t port); /* these versions are linked to physical addresses */ -void out8_phys(uint16_t port, uint8_t value); -uint8_t in8_phys(uint16_t port); +static inline void SECTION(".phys.text") +out8_phys(uint16_t port, uint8_t value) +{ + asm volatile("outb %[value], %[port]" :: [port] "d"(port), [value] "a"(value)); +} + +static inline uint8_t SECTION(".phys.text") +in8_phys(uint16_t port) +{ + uint8_t value; + asm volatile("inb %[port], %[value]" : [value] "=a"(value) : [port] "d" (port)); + return value; +} #ifdef DEBUG diff --git a/src/arch/ia32/machine_asm.S b/src/arch/ia32/machine_asm.S index 4b3436a3b..dfcf5f3d0 100644 --- a/src/arch/ia32/machine_asm.S +++ b/src/arch/ia32/machine_asm.S @@ -10,44 +10,8 @@ #include -.section .phys.text - -BEGIN_FUNC(out8_phys) - movb 8(%esp), %al - movw 4(%esp), %dx - outb %al, %dx - ret -END_FUNC(out8_phys) - -BEGIN_FUNC(in8_phys) - movw 4(%esp), %dx - inb %dx, %al - ret -END_FUNC(in8_phys) - .section .boot.text -BEGIN_FUNC(ia32_rdmsr_low) - movl 4(%esp), %ecx # MSR register index - rdmsr # 8 bytes output will be in EDX:EAX - ret -END_FUNC(ia32_rdmsr_low) - -BEGIN_FUNC(ia32_rdmsr_high) - movl 4(%esp), %ecx # MSR register index - rdmsr # 8 bytes output will be in EDX:EAX - movl %edx, %eax # Move the high bytes to the return register - ret -END_FUNC(ia32_rdmsr_high) - -BEGIN_FUNC(ia32_wrmsr) - movl 4(%esp), %ecx # MSR register index - movl 8(%esp), %edx # 4 most significant bytes - movl 12(%esp), %eax # 4 least significant bytes - wrmsr - ret -END_FUNC(ia32_wrmsr) - BEGIN_FUNC(ia32_install_gdt) movl 4(%esp), %eax lgdt (%eax) # load gdtr register with gdt pointer @@ -78,23 +42,6 @@ BEGIN_FUNC(ia32_install_tss) ret END_FUNC(ia32_install_tss) -BEGIN_FUNC(read_cr4) - movl %cr4, %eax - ret -END_FUNC(read_cr4) - -BEGIN_FUNC(write_cr0) - movl 4(%esp), %eax - movl %eax, %cr0 - ret -END_FUNC(write_cr0) - -BEGIN_FUNC(write_cr4) - movl 4(%esp), %eax - movl %eax, %cr4 - ret -END_FUNC(write_cr4) - BEGIN_FUNC(getCacheLineSize) pushl %ebx movl $1, %eax @@ -107,90 +54,8 @@ BEGIN_FUNC(getCacheLineSize) ret END_FUNC(getCacheLineSize) -BEGIN_FUNC(ia32_cpuid_edx) - movl 4(%esp), %eax - movl 8(%esp), %ecx - pushl %ebx - cpuid - popl %ebx - movl %edx, %eax - ret -END_FUNC(ia32_cpuid_edx) - -BEGIN_FUNC(ia32_cpuid_eax) - movl 4(%esp), %eax - movl 8(%esp), %ecx - pushl %ebx - cpuid - popl %ebx - ret -END_FUNC(ia32_cpuid_eax) - .section .text -BEGIN_FUNC(invalidateTLB) - movl %cr3, %eax - movl %eax, %cr3 - ret -END_FUNC(invalidateTLB) - -BEGIN_FUNC(invalidateTLBentry) - movl 4(%esp), %eax - invlpg (%eax) - ret -END_FUNC(invalidateTLBentry) - -BEGIN_FUNC(invalidatePageStructureCache) - // Force an invalidate by flushing an arbitrary entry - // from the TLB - movl $0, %eax - invlpg (%eax) - ret -END_FUNC(invalidatePageStructureCache) - -BEGIN_FUNC(flushCacheLine) - movl 4(%esp), %eax - clflush (%eax) - ret -END_FUNC(flushCacheLine) - -BEGIN_FUNC(getFaultAddr) - movl %cr2, %eax - ret -END_FUNC(getFaultAddr) - -BEGIN_FUNC(get_current_esp) - movl %esp, %eax - ret -END_FUNC(get_current_esp) - -BEGIN_FUNC(ia32_wbinvd) - wbinvd - ret -END_FUNC(ia32_wbinvd) - -BEGIN_FUNC(ia32_mfence) - mfence - ret -END_FUNC(ia32_mfence) - -BEGIN_FUNC(saveFpuState) - movl 4(%esp), %eax - fxsave (%eax) - ret -END_FUNC(saveFpuState) - -BEGIN_FUNC(loadFpuState) - movl 4(%esp), %eax - fxrstor (%eax) - ret -END_FUNC(loadFpuState) - -BEGIN_FUNC(resetFpu) - finit - ret -END_FUNC(resetFpu) - BEGIN_FUNC(out8) movb 8(%esp), %al movw 4(%esp), %dx From 952e5a272b5077ce6550035fbc5e2d6c55d09670 Mon Sep 17 00:00:00 2001 From: Adrian Danis Date: Wed, 13 May 2015 16:46:58 +1000 Subject: [PATCH 19/19] Add ability to set a human readable thread name when running kernel in debug mode --- include/api/syscall.xml | 1 + include/api/types.h | 4 +- include/arch/arm/arch/object/structures.h | 5 ++ include/arch/ia32/arch/object/structures.h | 5 ++ include/object/tcb.h | 8 +++ include/string.h | 24 +++++++++ libsel4/arch_include/arm/sel4/arch/syscalls.h | 17 +++++++ .../arch_include/ia32/sel4/arch/syscalls.h | 21 ++++++++ libsel4/include/api/syscall.xml | 1 + src/Makefile | 3 +- src/api/syscall.c | 27 ++++++++++ src/kernel/boot.c | 4 ++ src/kernel/faulthandler.c | 2 +- src/object/objecttype.c | 7 +++ src/object/tcb.c | 9 ++++ src/string.c | 49 +++++++++++++++++++ 16 files changed, 183 insertions(+), 4 deletions(-) create mode 100644 include/string.h create mode 100644 src/string.c diff --git a/include/api/syscall.xml b/include/api/syscall.xml index cffc68809..54cc35f73 100644 --- a/include/api/syscall.xml +++ b/include/api/syscall.xml @@ -29,6 +29,7 @@ + diff --git a/include/api/types.h b/include/api/types.h index 840df9c73..b1770ccbb 100644 --- a/include/api/types.h +++ b/include/api/types.h @@ -112,8 +112,8 @@ wordFromMessageInfo(message_info_t mi) #define userError(...) \ do { \ printf(ANSI_DARK "<<" ANSI_GREEN "seL4" ANSI_DARK \ - " [%s/%d T%x @%x]: ", \ - __func__, __LINE__, (int)ksCurThread, \ + " [%s/%d T%x \"%s\" @%x]: ", \ + __func__, __LINE__, (int)ksCurThread, ksCurThread->tcbName, \ (int)getRestartPC(ksCurThread)); \ printf(__VA_ARGS__); \ printf(">>" ANSI_RESET "\n"); \ diff --git a/include/arch/arm/arch/object/structures.h b/include/arch/arm/arch/object/structures.h index 3c74e3fe1..4ed36d65a 100644 --- a/include/arch/arm/arch/object/structures.h +++ b/include/arch/arm/arch/object/structures.h @@ -194,6 +194,11 @@ struct tcb { /* Previous and next pointers for endpoint & scheduler queues, 16 bytes */ struct tcb *tcbSchedNext, *tcbSchedPrev, *tcbEPNext, *tcbEPPrev; + +#ifdef DEBUG + /* Use any remaining space for a thread name */ + char tcbName[]; +#endif }; typedef struct tcb tcb_t; diff --git a/include/arch/ia32/arch/object/structures.h b/include/arch/ia32/arch/object/structures.h index 994bcbffa..54ce8ccaa 100644 --- a/include/arch/ia32/arch/object/structures.h +++ b/include/arch/ia32/arch/object/structures.h @@ -196,6 +196,11 @@ struct tcb { struct tcb* tcbSchedPrev; struct tcb* tcbEPNext; struct tcb* tcbEPPrev; + +#ifdef DEBUG + /* Use any remaining space for a thread name */ + char tcbName[]; +#endif }; typedef struct tcb tcb_t; diff --git a/include/object/tcb.h b/include/object/tcb.h index b26e2f62a..36f88a741 100644 --- a/include/object/tcb.h +++ b/include/object/tcb.h @@ -18,6 +18,11 @@ #include #include +#ifdef DEBUG +/* Maximum length of the tcb name, including null terminator */ +#define TCB_NAME_LENGTH (BIT(TCB_SIZE_BITS) - sizeof(tcb_t)) +#endif + struct tcb_queue { tcb_t *head; tcb_t *end; @@ -84,5 +89,8 @@ cptr_t PURE getExtraCPtr(word_t *bufferPtr, unsigned int i); void setExtraBadge(word_t *bufferPtr, word_t badge, unsigned int i); exception_t lookupExtraCaps(tcb_t* thread, word_t *bufferPtr, message_info_t info); +#ifdef DEBUG +void setThreadName(tcb_t *thread, const char *name); +#endif #endif diff --git a/include/string.h b/include/string.h new file mode 100644 index 000000000..a67aeecf5 --- /dev/null +++ b/include/string.h @@ -0,0 +1,24 @@ +/* + * Copyright 2014, General Dynamics C4 Systems + * + * This software may be distributed and modified according to the terms of + * the GNU General Public License version 2. Note that NO WARRANTY is provided. + * See "LICENSE_GPLv2.txt" for details. + * + * @TAG(GD_GPL) + */ + +#ifndef __STRING_H +#define __STRING_H + +#ifdef DEBUG + +#include + +unsigned int strnlen(const char *s, unsigned int maxlen); +unsigned int strlcpy(char *dest, const char *src, unsigned int size); +unsigned int strlcat(char *dest, const char *src, unsigned int size); + +#endif + +#endif diff --git a/libsel4/arch_include/arm/sel4/arch/syscalls.h b/libsel4/arch_include/arm/sel4/arch/syscalls.h index 3616bb715..c1ad37ab6 100644 --- a/libsel4/arch_include/arm/sel4/arch/syscalls.h +++ b/libsel4/arch_include/arm/sel4/arch/syscalls.h @@ -519,6 +519,23 @@ seL4_DebugCapIdentify(seL4_CPtr cap) } #endif +#ifdef SEL4_DEBUG_KERNEL + +char *strcpy(char *, const char *); +static inline void +seL4_DebugNameThread(seL4_CPtr tcb, const char *name) +{ + strcpy((char*)seL4_GetIPCBuffer()->msg, name); + + register seL4_Word arg1 asm("r0") = tcb; + register seL4_Word scno asm("r7") = seL4_SysDebugNameThread; + asm volatile ("swi %[swi_num]" + : "+r"(arg1) + : [swi_num] "i" __SWINUM(seL4_SysDebugNameThread), "r"(scno) + : "memory"); +} +#endif + #ifdef SEL4_DANGEROUS_CODE_INJECTION_KERNEL static inline void seL4_DebugRun(void (* userfn) (void *), void* userarg) diff --git a/libsel4/arch_include/ia32/sel4/arch/syscalls.h b/libsel4/arch_include/ia32/sel4/arch/syscalls.h index 41f495226..053184a61 100644 --- a/libsel4/arch_include/ia32/sel4/arch/syscalls.h +++ b/libsel4/arch_include/ia32/sel4/arch/syscalls.h @@ -501,6 +501,27 @@ seL4_DebugCapIdentify(seL4_CPtr cap) } #endif +#ifdef SEL4_DEBUG_KERNEL +char *strcpy(char *, const char *); +static inline void +seL4_DebugNameThread(seL4_CPtr tcb, const char *name) +{ + strcpy((char*)seL4_GetIPCBuffer()->msg, name); + + asm volatile ( + "pushl %%ebp \n" + "movl %%esp, %%ecx \n" + "leal 1f, %%edx \n" + "1: \n" + "sysenter \n" + "popl %%ebp \n" + : + : "a"(seL4_SysDebugNameThread), "b"(tcb) + : "%ecx", "%edx", "%esi", "%edi", "memory" + ); +} +#endif + #if defined(SEL4_DANGEROUS_CODE_INJECTION_KERNEL) static inline void seL4_DebugRun(void (*userfn) (void *), void* userarg) diff --git a/libsel4/include/api/syscall.xml b/libsel4/include/api/syscall.xml index 23921ac50..93dabde8e 100644 --- a/libsel4/include/api/syscall.xml +++ b/libsel4/include/api/syscall.xml @@ -29,6 +29,7 @@ + diff --git a/src/Makefile b/src/Makefile index 06e87a9bf..a7c2acfb5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,5 +16,6 @@ include ${SOURCE_ROOT}/src/machine/Makefile C_SOURCES += src/inlines.c \ src/assert.c \ - src/util.c + src/util.c \ + src/string.c diff --git a/src/api/syscall.c b/src/api/syscall.c index ae72d62d7..097f81e84 100644 --- a/src/api/syscall.c +++ b/src/api/syscall.c @@ -20,6 +20,7 @@ #include #include #include +#include #ifdef DEBUG #include @@ -71,6 +72,32 @@ handleUnknownSyscall(word_t w) setRegister(ksCurThread, capRegister, cap_type); return EXCEPTION_NONE; } + if (w == SysDebugNameThread) { + /* This is a syscall meant to aid debugging, so if anything goes wrong wrong + * then assume the system is completely misconfigured and halt */ + const char *name; + word_t cptr = getRegister(ksCurThread, capRegister); + lookupCapAndSlot_ret_t lu_ret = lookupCapAndSlot(ksCurThread, cptr); + /* ensure we got a TCB cap */ + uint32_t cap_type = cap_get_capType(lu_ret.cap); + if (cap_type != cap_thread_cap) { + userError("SysDebugNameThread: cap is not a TCB, halting"); + halt(); + } + /* Add 1 to the IPC buffer to skip the message info word */ + name = (const char*)(lookupIPCBuffer(true, ksCurThread) + 1); + if (!name) { + userError("SysDebugNameThread: Failed to lookup IPC buffer, halting"); + halt(); + } + /* ensure the name isn't too long */ + if (name[strnlen(name, seL4_MsgMaxLength * sizeof(word_t))] != '\0') { + userError("SysDebugNameThread: Name too long, halting"); + halt(); + } + setThreadName(TCB_PTR(cap_thread_cap_get_capTCBPtr(lu_ret.cap)), name); + return EXCEPTION_NONE; + } #endif #ifdef DANGEROUS_CODE_INJECTION diff --git a/src/kernel/boot.c b/src/kernel/boot.c index c8816c851..dc04a625c 100644 --- a/src/kernel/boot.c +++ b/src/kernel/boot.c @@ -427,6 +427,10 @@ create_initial_thread( cap = cap_thread_cap_new(TCB_REF(tcb)); write_slot(SLOT_PTR(pptr_of_cap(root_cnode_cap), BI_CAP_IT_TCB), cap); +#ifdef DEBUG + setThreadName(tcb, "rootserver"); +#endif + return true; } diff --git a/src/kernel/faulthandler.c b/src/kernel/faulthandler.c index 05da65356..1dbe97193 100644 --- a/src/kernel/faulthandler.c +++ b/src/kernel/faulthandler.c @@ -111,7 +111,7 @@ handleDoubleFault(tcb_t *tptr, fault_t ex1) print_fault(ex2); printf("\nwhile trying to handle:\n"); print_fault(ex1); - printf("\nin thread 0x%x ", (unsigned int)tptr); + printf("\nin thread 0x%x \"%s\" ", (unsigned int)tptr, tptr->tcbName); printf("at address 0x%x\n", (unsigned int)getRestartPC(tptr)); #endif diff --git a/src/object/objecttype.c b/src/object/objecttype.c index 552ea65d4..bc9d0c193 100644 --- a/src/object/objecttype.c +++ b/src/object/objecttype.c @@ -29,6 +29,7 @@ #include #include #include +#include word_t getObjectSize(word_t t, word_t userObjSize) { @@ -513,6 +514,12 @@ createObject(object_t t, void *regionBase, word_t userSize) tcb->tcbTimeSlice = CONFIG_TIME_SLICE; tcb->tcbDomain = ksCurDomain; +#ifdef DEBUG + strlcpy(tcb->tcbName, "child of: '", TCB_NAME_LENGTH); + strlcat(tcb->tcbName, ksCurThread->tcbName, TCB_NAME_LENGTH); + strlcat(tcb->tcbName, "'", TCB_NAME_LENGTH); +#endif + return cap_thread_cap_new(TCB_REF(tcb)); } diff --git a/src/object/tcb.c b/src/object/tcb.c index 07b3f8ba9..cee2761f0 100644 --- a/src/object/tcb.c +++ b/src/object/tcb.c @@ -22,6 +22,7 @@ #include #include #include +#include static inline PURE unsigned int @@ -989,3 +990,11 @@ invokeTCB_WriteRegisters(tcb_t *dest, bool_t resumeTarget, return EXCEPTION_NONE; } + +#ifdef DEBUG +void +setThreadName(tcb_t *tcb, const char *name) +{ + strlcpy(tcb->tcbName, name, TCB_NAME_LENGTH); +} +#endif diff --git a/src/string.c b/src/string.c new file mode 100644 index 000000000..527931058 --- /dev/null +++ b/src/string.c @@ -0,0 +1,49 @@ +/* + * Copyright 2014, General Dynamics C4 Systems + * + * This software may be distributed and modified according to the terms of + * the GNU General Public License version 2. Note that NO WARRANTY is provided. + * See "LICENSE_GPLv2.txt" for details. + * + * @TAG(GD_GPL) + */ + +#include +#include + +#ifdef DEBUG + +unsigned int strnlen(const char *s, unsigned int maxlen) +{ + unsigned int len; + for (len = 0; len < maxlen && s[len]; len++); + return len; +} + +unsigned int strlcpy(char *dest, const char *src, unsigned int size) +{ + unsigned int len; + for (len = 0; len + 1 < size && src[len]; len++) { + dest[len] = src[len]; + } + dest[len] = '\0'; + return len; +} + +unsigned int strlcat(char *dest, const char *src, unsigned int size) +{ + unsigned int len; + /* get to the end of dest */ + for (len = 0; len < size && dest[len]; len++); + /* check that dest was at least 'size' length to prevent inserting + * a null byte when we shouldn't */ + if (len < size) { + for (; len + 1 < size && *src; len++, src++) { + dest[len] = *src; + } + dest[len] = '\0'; + } + return len; +} + +#endif