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. 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 diff --git a/Kconfig b/Kconfig index 26ccd9dcc..7534977a4 100644 --- a/Kconfig +++ b/Kconfig @@ -382,6 +382,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/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} ) 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/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 b37eba6ee..76f8471d7 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/arm/arch/machine/registerset.h b/include/arch/arm/arch/machine/registerset.h index 44388db0d..58a4ec301 100644 --- a/include/arch/arm/arch/machine/registerset.h +++ b/include/arch/arm/arch/machine/registerset.h @@ -33,6 +33,10 @@ | PMODE_KERNEL \ | 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/include/arch/arm/arch/object/structures.h b/include/arch/arm/arch/object/structures.h index 5f987a560..0cf3f3348 100644 --- a/include/arch/arm/arch/object/structures.h +++ b/include/arch/arm/arch/object/structures.h @@ -200,6 +200,10 @@ struct tcb { * tcb->vcpu->tcb == tcb. */ struct vcpu* vcpu; #endif +#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/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/include/arch/ia32/arch/machine.h b/include/arch/ia32/arch/machine.h index a033bc046..eba9f5f70 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); @@ -41,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); @@ -63,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) @@ -78,18 +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); +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 190d5195c..84a3e70e1 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 @@ -84,7 +85,14 @@ 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 */ +bool_t disablePrefetchers(void); + #endif 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/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 */ 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/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/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/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/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/libsel4/arch_include/arm/interfaces/sel4arch.xml b/libsel4/arch_include/arm/interfaces/sel4arch.xml index a814a2ba1..09982b545 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/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/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/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/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; 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) --> - + - + + - - + + diff --git a/libsel4/tools/syscall_stub_gen.py b/libsel4/tools/syscall_stub_gen.py index c89fa0703..8d2ec1a9b 100644 --- a/libsel4/tools/syscall_stub_gen.py +++ b/libsel4/tools/syscall_stub_gen.py @@ -235,6 +235,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: @@ -287,7 +293,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. @@ -335,7 +341,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) @@ -437,7 +443,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: @@ -478,7 +484,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:] @@ -561,8 +567,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)) @@ -598,12 +605,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") @@ -631,7 +642,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): """ @@ -646,11 +657,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(""" @@ -712,7 +723,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 */") 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/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); } diff --git a/src/arch/arm/kernel/boot.c b/src/arch/arm/kernel/boot.c index 45948c361..15fcfde2a 100644 --- a/src/arch/arm/kernel/boot.c +++ b/src/arch/arm/kernel/boot.c @@ -172,10 +172,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 60543b5d6..07ca6a67c 100644 --- a/src/arch/arm/kernel/vspace.c +++ b/src/arch/arm/kernel/vspace.c @@ -165,7 +165,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; @@ -189,7 +189,7 @@ map_it_frame_cap(cap_t pd_cap, cap_t frame_cap) APFromVMRights(VMReadWrite), 1, /* cacheable */ 1, /* write-back caching */ - 0 /* executable */ + !executable ); #else *targetSlot = pte_pte_small_new( @@ -364,7 +364,7 @@ map_kernel_window(void) PPTR_GLOBALS_PAGE, VMReadOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ true, /* armParityEnabled */ true /* armPageCacheable */ ) @@ -376,7 +376,7 @@ map_kernel_window(void) PPTR_KERNEL_STACK, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ true, /* armParityEnabled */ true /* armPageCacheable */ ) @@ -1839,6 +1839,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 = @@ -1958,6 +1959,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; diff --git a/src/arch/ia32/kernel/boot.c b/src/arch/ia32/kernel/boot.c index 007fa4aa2..5a0a83d6d 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); @@ -575,5 +576,11 @@ init_node_cpu( 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..42dfedce2 100644 --- a/src/arch/ia32/machine/hardware.c +++ b/src/arch/ia32/machine/hardware.c @@ -82,3 +82,38 @@ 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..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,81 +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) - .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 diff --git a/src/kernel/boot.c b/src/kernel/boot.c index fc702747d..dc04a625c 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); } @@ -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/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..795fb8df5 100644 --- a/src/plat/am335x/machine/hardware.c +++ b/src/plat/am335x/machine/hardware.c @@ -42,16 +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: */ -#ifndef DEBUG - { /* .start = */ UART0_PADDR, /* .end = */ UART0_PADDR + (1 << PAGE_BITS) }, -#endif + { /* .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. */ }; @@ -76,7 +75,7 @@ map_kernel_devices(void) DMTIMER0_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -88,7 +87,7 @@ map_kernel_devices(void) INTC_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -100,7 +99,19 @@ map_kernel_devices(void) WDT1_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ + false, /* armParityEnabled */ + false /* armPageCacheable */ + ) + ); + + /* map kernel device: CMPER */ + map_kernel_frame( + CMPER_PADDR, + CMPER_PPTR, + VMKernelOnly, + vm_attributes_new( + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -113,7 +124,7 @@ map_kernel_devices(void) UART0_PPTR, VMKernelOnly, vm_attributes_new( - false, /* armExecuteNever */ + true, /* armExecuteNever */ false, /* armParityEnabled */ false /* armPageCacheable */ ) @@ -121,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) @@ -297,6 +315,29 @@ 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 @@ -307,6 +348,7 @@ initTimer(void) int timeout; disableWatchdog(); + enableTimers(); timer->cfg = TIOCP_CFG_SOFTRESET; 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 1a9ece201..24e18a0a8 100644 --- a/src/plat/exynos5/machine/hardware.c +++ b/src/plat/exynos5/machine/hardware.c @@ -318,7 +318,7 @@ map_kernel_devices(void) MCT_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 */ ) @@ -364,7 +364,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 */ ) 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