853 lines
28 KiB
C
853 lines
28 KiB
C
/* nano_private.h - private nanokernel definitions (IA-32) */
|
||
|
||
/*
|
||
* Copyright (c) 2010-2014 Wind River Systems, Inc.
|
||
*
|
||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
|
||
/*
|
||
* DESCRIPTION
|
||
* This file contains private nanokernel structures definitions and various
|
||
* other definitions for the Intel Architecture 32 bit (IA-32) processor
|
||
* architecture.
|
||
* The header include/nanokernel.h contains the public nanokernel interface
|
||
* definitions, with include/arch/nanokernel/x86/arch.h supplying the
|
||
* IA-32 specific portions of the public nanokernel interface.
|
||
*
|
||
* This file is also included by assembly language files which must #define
|
||
* _ASMLANGUAGE before including this header file. Note that nanokernel
|
||
* assembly source files obtains structure offset values via "absolute symbols"
|
||
* in the offsets.o module.
|
||
*/
|
||
|
||
#ifndef _NANO_PRIVATE_H
|
||
#define _NANO_PRIVATE_H
|
||
|
||
#include <toolchain.h>
|
||
#include <sections.h>
|
||
#include <asm_inline.h>
|
||
|
||
#ifndef _ASMLANGUAGE
|
||
#include <nanokernel.h> /* public nanokernel API */
|
||
#include <../../../kernel/nanokernel/include/nano_internal.h>
|
||
#include <stdint.h>
|
||
/*
|
||
* This pulls in the code shared with the IDT generator that actually
|
||
* constructs an IDT entry.
|
||
*/
|
||
#include <idtEnt.h>
|
||
#include <misc/dlist.h>
|
||
#endif
|
||
|
||
/* increase to 16 bytes (or more?) to support SSE/SSE2 instructions? */
|
||
|
||
#define STACK_ALIGN_SIZE 4
|
||
|
||
/*
|
||
* Bitmask definitions for the struct tcs->flags bit field
|
||
*
|
||
* The USE_FP flag bit will be set whenever a thread uses any non-integer
|
||
* capability, whether it's just the x87 FPU capability, SSE instructions, or
|
||
* a combination of both. The USE_SSE flag bit will only be set if a thread
|
||
* uses SSE instructions.
|
||
*
|
||
* Note: Any change to the definitions USE_FP and USE_SSE must also be made to
|
||
* nanokernel/x86/arch.h.
|
||
*/
|
||
|
||
#define FIBER 0
|
||
#define TASK 0x1 /* 1 = task, 0 = fiber */
|
||
#define INT_ACTIVE 0x2 /* 1 = executing context is interrupt handler */
|
||
#define EXC_ACTIVE 0x4 /* 1 = executing context is exception handler */
|
||
#define USE_FP 0x10 /* 1 = thread uses floating point unit */
|
||
#define USE_SSE 0x20 /* 1 = thread uses SSEx instructions */
|
||
#define PREEMPTIBLE 0x100 /* 1 = preemptible thread */
|
||
#define ESSENTIAL 0x200 /* 1 = system thread that must not abort */
|
||
#define NO_METRICS 0x400 /* 1 = _Swap() not to update task metrics */
|
||
#define NO_METRICS_BIT_OFFSET 0xa /* Bit position of NO_METRICS */
|
||
|
||
#define INT_OR_EXC_MASK (INT_ACTIVE | EXC_ACTIVE)
|
||
|
||
/*
|
||
* Exception/interrupt vector definitions: vectors 20 to 31 are reserved for
|
||
* Intel; vectors 32 to 255 are user defined interrupt vectors.
|
||
*/
|
||
|
||
#define IV_DIVIDE_ERROR 0
|
||
#define IV_DEBUG 1
|
||
#define IV_NON_MASKABLE_INTERRUPT 2
|
||
#define IV_BREAKPOINT 3
|
||
#define IV_OVERFLOW 4
|
||
#define IV_BOUND_RANGE 5
|
||
#define IV_INVALID_OPCODE 6
|
||
#define IV_DEVICE_NOT_AVAILABLE 7
|
||
#define IV_DOUBLE_FAULT 8
|
||
#define IV_COPROC_SEGMENT_OVERRUN 9
|
||
#define IV_INVALID_TSS 10
|
||
#define IV_SEGMENT_NOT_PRESENT 11
|
||
#define IV_STACK_FAULT 12
|
||
#define IV_GENERAL_PROTECTION 13
|
||
#define IV_PAGE_FAULT 14
|
||
#define IV_RESERVED 15
|
||
#define IV_X87_FPU_FP_ERROR 16
|
||
#define IV_ALIGNMENT_CHECK 17
|
||
#define IV_MACHINE_CHECK 18
|
||
#define IV_SIMD_FP 19
|
||
#define IV_INTEL_RESERVED_END 31
|
||
|
||
/*
|
||
* Model specific register (MSR) definitions. Use the _MsrRead() and
|
||
* _MsrWrite() primitives to read/write the MSRs. Only the so-called
|
||
* "Architectural MSRs" are listed, i.e. the subset of MSRs and associated
|
||
* bit fields which will not change on future processor generations.
|
||
*/
|
||
|
||
#define IA32_P5_MC_ADDR_MSR 0x0000
|
||
#define IA32_P5_MC_TYPE_MSR 0x0001
|
||
#define IA32_MONITOR_FILTER_SIZE_MSR 0x0006
|
||
#define IA32_TIME_STAMP_COUNTER_MSR 0x0010
|
||
#define IA32_IA32_PLATFORM_ID_MSR 0x0017
|
||
#define IA32_APIC_BASE_MSR 0x001b
|
||
#define IA32_FEATURE_CONTROL_MSR 0x003a
|
||
#define IA32_BIOS_SIGN_MSR 0x008b
|
||
#define IA32_SMM_MONITOR_CTL_MSR 0x009b
|
||
#define IA32_PMC0_MSR 0x00c1
|
||
#define IA32_PMC1_MSR 0x00c2
|
||
#define IA32_PMC2_MSR 0x00c3
|
||
#define IA32_PMC3_MSR 0x00c4
|
||
#define IA32_MPERF_MSR 0x00e7
|
||
#define IA32_APERF_MSR 0x00e8
|
||
#define IA32_MTRRCAP_MSR 0x00fe
|
||
#define IA32_SYSENTER_CS_MSR 0x0174
|
||
#define IA32_SYSENTER_ESP_MSR 0x0175
|
||
#define IA32_SYSENTER_EIP_MSR 0x0176
|
||
#define IA32_MCG_CAP_MSR 0x0179
|
||
#define IA32_MCG_STATUS_MSR 0x017a
|
||
#define IA32_MCG_CTL_MSR 0x017b
|
||
#define IA32_PERFEVTSEL0_MSR 0x0186
|
||
#define IA32_PERFEVTSEL1_MSR 0x0187
|
||
#define IA32_PERFEVTSEL2_MSR 0x0188
|
||
#define IA32_PERFEVTSEL3_MSR 0x0188
|
||
#define IA32_PERF_STATUS_MSR 0x0198
|
||
#define IA32_PERF_CTL_MSR 0x0199
|
||
#define IA32_CLOCK_MODULATION_MSR 0x019a
|
||
#define IA32_THERM_INTERRUPT_MSR 0x019b
|
||
#define IA32_THERM_STATUS_MSR 0x019c
|
||
#define IA32_MISC_ENABLE_MSR 0x01a0
|
||
#define IA32_ENERGY_PERF_BIAS_MSR 0x01b0
|
||
#define IA32_DEBUGCTL_MSR 0x01d9
|
||
#define IA32_SMRR_PHYSBASE_MSR 0x01f2
|
||
#define IA32_SMRR_PHYSMASK_MSR 0x01f3
|
||
#define IA32_PLATFORM_DCA_CAP_MSR 0x01f8
|
||
#define IA32_CPU_DCA_CAP_MSR 0x01f9
|
||
#define IA32_DCA_0_CAP_MSR 0x01fa
|
||
#define IA32_MTRR_PHYSBASE0_MSR 0x0200
|
||
#define IA32_MTRR_PHYSMASK0_MSR 0x0201
|
||
#define IA32_MTRR_PHYSBASE1_MSR 0x0202
|
||
#define IA32_MTRR_PHYSMASK1_MSR 0x0203
|
||
#define IA32_MTRR_PHYSBASE2_MSR 0x0204
|
||
#define IA32_MTRR_PHYSMASK2_MSR 0x0205
|
||
#define IA32_MTRR_PHYSBASE3_MSR 0x0206
|
||
#define IA32_MTRR_PHYSMASK3_MSR 0x0207
|
||
#define IA32_MTRR_PHYSBASE4_MSR 0x0208
|
||
#define IA32_MTRR_PHYSMASK4_MSR 0x0209
|
||
#define IA32_MTRR_PHYSBASE5_MSR 0x020a
|
||
#define IA32_MTRR_PHYSMASK5_MSR 0x020b
|
||
#define IA32_MTRR_PHYSBASE6_MSR 0x020c
|
||
#define IA32_MTRR_PHYSMASK6_MSR 0x020d
|
||
#define IA32_MTRR_PHYSBASE7_MSR 0x020e
|
||
#define IA32_MTRR_PHYSMASK7_MSR 0x020f
|
||
#define IA32_MTRR_FIX64K_00000_MSR 0x0250
|
||
#define IA32_MTRR_FIX16K_80000_MSR 0x0258
|
||
#define IA32_MTRR_FIX16K_A0000_MSR 0x0259
|
||
#define IA32_MTRR_FIX4K_C0000_MSR 0x0268
|
||
#define IA32_MTRR_FIX4K_C8000_MSR 0x0269
|
||
#define IA32_MTRR_FIX4K_D0000_MSR 0x026a
|
||
#define IA32_MTRR_FIX4K_D8000_MSR 0x026b
|
||
#define IA32_MTRR_FIX4K_E0000_MSR 0x026c
|
||
#define IA32_MTRR_FIX4K_E8000_MSR 0x026d
|
||
#define IA32_MTRR_FIX4K_F0000_MSR 0x026e
|
||
#define IA32_MTRR_FIX4K_F8000_MSR 0x026f
|
||
#define IA32_PAT_MSR 0x0277
|
||
#define IA32_MC0_CTL2_MSR 0x0280
|
||
#define IA32_MC1_CTL2_MSR 0x0281
|
||
#define IA32_MC2_CTL2_MSR 0x0282
|
||
#define IA32_MC3_CTL2_MSR 0x0283
|
||
#define IA32_MC4_CTL2_MSR 0x0284
|
||
#define IA32_MC5_CTL2_MSR 0x0285
|
||
#define IA32_MC6_CTL2_MSR 0x0286
|
||
#define IA32_MC7_CTL2_MSR 0x0287
|
||
#define IA32_MC8_CTL2_MSR 0x0288
|
||
#define IA32_MC9_CTL2_MSR 0x0289
|
||
#define IA32_MC10_CTL2_MSR 0x028a
|
||
#define IA32_MC11_CTL2_MSR 0x028b
|
||
#define IA32_MC12_CTL2_MSR 0x028c
|
||
#define IA32_MC13_CTL2_MSR 0x028d
|
||
#define IA32_MC14_CTL2_MSR 0x028e
|
||
#define IA32_MC15_CTL2_MSR 0x028f
|
||
#define IA32_MC16_CTL2_MSR 0x0290
|
||
#define IA32_MC17_CTL2_MSR 0x0291
|
||
#define IA32_MC18_CTL2_MSR 0x0292
|
||
#define IA32_MC19_CTL2_MSR 0x0293
|
||
#define IA32_MC20_CTL2_MSR 0x0294
|
||
#define IA32_MC21_CTL2_MSR 0x0295
|
||
#define IA32_MTRR_DEF_TYPE_MSR 0x02ff
|
||
#define IA32_FIXED_CTR0_MSR 0x0309
|
||
#define IA32_FIXED_CTR1_MSR 0x030a
|
||
#define IA32_FIXED_CTR2_MSR 0x030b
|
||
#define IA32_PERF_CAPABILITIES_MSR 0x0345
|
||
#define IA32_FIXED_CTR_CTL_MSR 0x038d
|
||
#define IA32_PERF_GLOBAL_STATUS_MSR 0x038e
|
||
#define IA32_PERF_GLOBAL_CTRL_MSR 0x038f
|
||
#define IA32_PERF_GLOBAL_OVF_CTRL_MSR 0x0390
|
||
#define IA32_PEBS_ENABLE_MSR 0x03f1
|
||
#define IA32_MC0_CTL_MSR 0x0400
|
||
#define IA32_MC0_STATUS 0x0401
|
||
#define IA32_MC0_ADDR_MSR 0x0402
|
||
#define IA32_MC0_MISC_MSR 0x0403
|
||
#define IA32_MC1_CTL_MSR 0x0404
|
||
#define IA32_MC1_STATUS_MSR 0x0405
|
||
#define IA32_MC1_ADDR_MSR 0x0406
|
||
#define IA32_MC1_MISC_MSR 0x0407
|
||
#define IA32_MC2_CTL_MSR 0x0408
|
||
#define IA32_MC2_STATUS_MSR 0x0409
|
||
#define IA32_MC2_ADDR_MSR 0x040a
|
||
#define IA32_MC2_MISC_MSR 0x040b
|
||
#define IA32_MC3_CTL_MSR 0x040c
|
||
#define IA32_MC3_STATUS_MSR 0x040d
|
||
#define IA32_MC3_ADDR_MSR 0x040e
|
||
#define IA32_MC3_MISC_MSR 0x040f
|
||
#define IA32_MC4_CTL_MSR 0x0410
|
||
#define IA32_MC4_STATUS_MSR 0x0411
|
||
#define IA32_MC4_ADDR_MSR 0x0412
|
||
#define IA32_MC4_MISC_MSR 0x0413
|
||
#define IA32_MC5_CTL_MSR 0x0414
|
||
#define IA32_MC5_STATUS_MSR 0x0415
|
||
#define IA32_MC5_ADDR_MSR 0x0416
|
||
#define IA32_MC5_MISC_MSR 0x0417
|
||
#define IA32_MC6_CTL_MSR 0x0418
|
||
#define IA32_MC6_STATUS_MSR 0x0419
|
||
#define IA32_MC6_ADDR_MSR 0x041a
|
||
#define IA32_MC6_MISC_MSR 0x041b
|
||
#define IA32_MC7_CTL_MSR 0x041c
|
||
#define IA32_MC7_STATUS_MSR 0x041d
|
||
#define IA32_MC7_ADDR_MSR 0x041e
|
||
#define IA32_MC7_MISC_MSR 0x041f
|
||
#define IA32_MC8_CTL_MSR 0x0420
|
||
#define IA32_MC8_STATUS_MSR 0x0421
|
||
#define IA32_MC8_ADDR_MSR 0x0422
|
||
#define IA32_MC8_MISC_MSR 0x0423
|
||
#define IA32_MC9_CTL_MSR 0x0424
|
||
#define IA32_MC9_STATUS_MSR 0x0425
|
||
#define IA32_MC9_ADDR_MSR 0x0426
|
||
#define IA32_MC9_MISC_MSR 0x0427
|
||
#define IA32_MC9_CTL_MSR 0x0424
|
||
#define IA32_MC9_STATUS_MSR 0x0425
|
||
#define IA32_MC9_ADDR_MSR 0x0426
|
||
#define IA32_MC9_MISC_MSR 0x0427
|
||
#define IA32_MC9_CTL_MSR 0x0424
|
||
#define IA32_MC9_STATUS_MSR 0x0425
|
||
#define IA32_MC9_ADDR_MSR 0x0426
|
||
#define IA32_MC9_MISC_MSR 0x0427
|
||
#define IA32_MC9_CTL_MSR 0x0424
|
||
#define IA32_MC9_STATUS_MSR 0x0425
|
||
#define IA32_MC9_ADDR_MSR 0x0426
|
||
#define IA32_MC9_MISC_MSR 0x0427
|
||
#define IA32_MC10_CTL_MSR 0x0428
|
||
#define IA32_MC10_STATUS_MSR 0x0429
|
||
#define IA32_MC10_ADDR_MSR 0x042a
|
||
#define IA32_MC10_MISC_MSR 0x042b
|
||
#define IA32_MC11_CTL_MSR 0x042c
|
||
#define IA32_MC11_STATUS_MSR 0x042d
|
||
#define IA32_MC11_ADDR_MSR 0x042e
|
||
#define IA32_MC11_MISC_MSR 0x042f
|
||
#define IA32_MC12_CTL_MSR 0x0430
|
||
#define IA32_MC12_STATUS_MSR 0x0431
|
||
#define IA32_MC12_ADDR_MSR 0x0432
|
||
#define IA32_MC12_MISC_MSR 0x0433
|
||
#define IA32_MC13_CTL_MSR 0x0434
|
||
#define IA32_MC13_STATUS_MSR 0x0435
|
||
#define IA32_MC13_ADDR_MSR 0x0436
|
||
#define IA32_MC13_MISC_MSR 0x0437
|
||
#define IA32_MC14_CTL_MSR 0x0438
|
||
#define IA32_MC14_STATUS_MSR 0x0439
|
||
#define IA32_MC14_ADDR_MSR 0x043a
|
||
#define IA32_MC14_MISC_MSR 0x043b
|
||
#define IA32_MC15_CTL_MSR 0x043c
|
||
#define IA32_MC15_STATUS_MSR 0x043d
|
||
#define IA32_MC15_ADDR_MSR 0x043e
|
||
#define IA32_MC15_MISC_MSR 0x043f
|
||
#define IA32_MC16_CTL_MSR 0x0440
|
||
#define IA32_MC16_STATUS_MSR 0x0441
|
||
#define IA32_MC16_ADDR_MSR 0x0442
|
||
#define IA32_MC16_MISC_MSR 0x0443
|
||
#define IA32_MC17_CTL_MSR 0x0444
|
||
#define IA32_MC17_STATUS_MSR 0x0445
|
||
#define IA32_MC17_ADDR_MSR 0x0446
|
||
#define IA32_MC17_MISC_MSR 0x0447
|
||
#define IA32_MC18_CTL_MSR 0x0448
|
||
#define IA32_MC18_STATUS_MSR 0x0449
|
||
#define IA32_MC18_ADDR_MSR 0x044a
|
||
#define IA32_MC18_MISC_MSR 0x044b
|
||
#define IA32_MC19_CTL_MSR 0x044c
|
||
#define IA32_MC19_STATUS_MSR 0x044d
|
||
#define IA32_MC19_ADDR_MSR 0x044e
|
||
#define IA32_MC19_MISC_MSR 0x044f
|
||
#define IA32_MC20_CTL_MSR 0x0450
|
||
#define IA32_MC20_STATUS_MSR 0x0451
|
||
#define IA32_MC20_ADDR_MSR 0x0452
|
||
#define IA32_MC20_MISC_MSR 0x0453
|
||
#define IA32_MC21_CTL_MSR 0x0454
|
||
#define IA32_MC21_STATUS_MSR 0x0455
|
||
#define IA32_MC21_ADDR_MSR 0x0456
|
||
#define IA32_MC21_MISC_MSR 0x0457
|
||
#define IA32_VMX_BASIC_MSR 0x0480
|
||
#define IA32_VMX_PINBASED_CTLS_MSR 0x0481
|
||
#define IA32_VMX_PROCBASED_CTLS_MSR 0x0482
|
||
#define IA32_VMX_EXIT_CTLS_MSR 0x0483
|
||
#define IA32_VMX_ENTRY_CTLS_MSR 0x0484
|
||
#define IA32_VMX_MISC_MSR 0x0485
|
||
#define IA32_VMX_CRO_FIXED0_MSR 0x0486
|
||
#define IA32_VMX_CRO_FIXED1_MSR 0x0487
|
||
#define IA32_VMX_CR4_FIXED0_MSR 0x0488
|
||
#define IA32_VMX_CR4_FIXED1_MSR 0x0489
|
||
#define IA32_VMX_VMCS_ENUM_MSR 0x048a
|
||
#define IA32_VMX_PROCBASED_CTLS2_MSR 0x048b
|
||
#define IA32_VMX_EPT_VPID_CAP_MSR 0x048c
|
||
#define IA32_VMX_TRUE_PINBASED_CTLS_MSR 0x048d
|
||
#define IA32_VMX_TRUE_PROCBASED_CTLS_MSR 0x048e
|
||
#define IA32_VMX_TRUE_EXIT_CTLS_MSR 0x048f
|
||
#define IA32_VMX_TRUE_ENTRY_CTLS_MSR 0x0490
|
||
#define IA32_DS_AREA_MSR 0x0600
|
||
#define IA32_EXT_XAPICID_MSR 0x0802
|
||
#define IA32_EXT_XAPIC_VERSION_MSR 0x0803
|
||
#define A32_EXT_XAPIC_TPR_MSR 0x0808
|
||
#define IA32_EXT_XAPIC_PPR_MSR 0x080a
|
||
#define IA32_EXT_XAPIC_EOI_MSR 0x080d
|
||
#define IA32_EXT_XAPIC_LDR_MSR 0x080c
|
||
#define IA32_EXT_XAPIC_SIVR_MSR 0x080f
|
||
#define IA32_EXT_XAPIC_ISR0_MSR 0x0810
|
||
#define IA32_EXT_XAPIC_ISR1_MSR 0x0811
|
||
#define A32_EXT_XAPIC_ISR2_MSR 0x0812
|
||
#define IA32_EXT_XAPIC_ISR3_MSR 0x0813
|
||
#define IA32_EXT_XAPIC_ISR4_MSR 0x0814
|
||
#define IA32_EXT_XAPIC_ISR5_MSR 0x0815
|
||
#define IA32_EXT_XAPIC_ISR6_MSR 0x0816
|
||
#define IA32_EXT_XAPIC_ISR7_MSR 0x0817
|
||
#define IA32_EXT_XAPIC_TMR0_MSR 0x0818
|
||
#define IA32_EXT_XAPIC_TMR1_MSR 0x0819
|
||
#define IA32_EXT_XAPIC_TMR2_MSR 0x081a
|
||
#define IA32_EXT_XAPIC_TMR3_MSR 0x081b
|
||
#define IA32_EXT_XAPIC_TMR4_MSR 0x081c
|
||
#define IA32_EXT_XAPIC_TMR5_MSR 0x081d
|
||
#define IA32_EXT_XAPIC_TMR6_MSR 0x081e
|
||
#define IA32_EXT_XAPIC_TMR7_MSR 0x081f
|
||
#define IA32_EXT_XAPIC_IRR0_MSR 0x0820
|
||
#define IA32_EXT_XAPIC_IRR1_MSR 0x0821
|
||
#define IA32_EXT_XAPIC_IRR2_MSR 0x0822
|
||
#define IA32_EXT_XAPIC_IRR3_MSR 0x0823
|
||
#define IA32_EXT_XAPIC_IRR4_MSR 0x0824
|
||
#define IA32_EXT_XAPIC_IRR5_MSR 0x0825
|
||
#define IA32_EXT_XAPIC_IRR6_MSR 0x0826
|
||
#define IA32_EXT_XAPIC_IRR7_MSR 0x0827
|
||
#define IA32_EXT_XAPIC_ESR_MSR 0x0828
|
||
#define IA32_EXT_XAPIC_LVT_CMCI_MSR 0x082f
|
||
#define IA32_EXT_XAPIC_ICR_MSR 0x0830
|
||
#define IA32_EXT_XAPIC_LVT_TIMER_MSR 0x0832
|
||
#define IA32_EXT_XAPIC_LVT_THERMAL_MSR 0x0833
|
||
#define IA32_EXT_XAPIC_LVT_PMI_MSR 0x0834
|
||
#define IA32_EXT_XAPIC_LVT_LINT0_MSR 0x0835
|
||
#define IA32_EXT_XAPIC_LVT_LINT1_MSR 0x0836
|
||
#define IA32_EXT_XAPIC_LVT_ERROR_MSR 0x0837
|
||
#define IA32_EXT_XAPIC_INIT_COUNT_MSR 0x0838
|
||
#define IA32_EXT_XAPIC_CUR_COUNT_MSR 0x0839
|
||
#define IA32_EXT_XAPIC_DIV_CONF_MSR 0x083e
|
||
#define IA32_EXT_XAPIC_SELF_IPI_MSR 0x083f
|
||
#define IA32_EFER_MSR 0xc0000080
|
||
#define IA32_STAR_MSR 0xc0000081
|
||
#define IA32_LSTAR_MSR 0xc0000082
|
||
#define IA32_FMASK_MSR 0xc0000084
|
||
#define IA32_FS_BASE_MSR 0xc0000100
|
||
#define IA32_GS_BASE_MSR 0xc0000101
|
||
#define IA32_KERNEL_GS_BASE_MSR 0xc0000102
|
||
#define IA32_TSC_AUX_MSR 0xc0000103
|
||
|
||
/*
|
||
* EFLAGS value to utilize for the initial context:
|
||
*
|
||
* IF (Interrupt Enable Flag) = 1
|
||
* IOPL bits = 0
|
||
* All other "flags" = Don't change state
|
||
*/
|
||
|
||
#define EFLAGS_INITIAL 0x00000200
|
||
#define EFLAGS_MASK 0x00003200
|
||
|
||
#ifndef _ASMLANGUAGE
|
||
|
||
#include <misc/util.h>
|
||
|
||
#ifdef DEBUG
|
||
#include <misc/printk.h>
|
||
#define PRINTK(...) printk(__VA_ARGS__)
|
||
#else
|
||
#define PRINTK(...)
|
||
#endif /* DEBUG */
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
/*
|
||
* The following structure defines the set of 'non-volatile' integer registers.
|
||
* These registers must be preserved by a called C function. These are the
|
||
* only registers that need to be saved/restored when a cooperative context
|
||
* switch occurs.
|
||
*/
|
||
|
||
typedef struct s_coopReg {
|
||
unsigned long esp;
|
||
|
||
/*
|
||
* The following registers are considered non-volatile, i.e.
|
||
* callee-save,
|
||
* but their values are pushed onto the stack rather than stored in the
|
||
* TCS
|
||
* structure:
|
||
*
|
||
* unsigned long ebp;
|
||
* unsigned long ebx;
|
||
* unsigned long esi;
|
||
* unsigned long edi;
|
||
*/
|
||
|
||
} tCoopReg;
|
||
|
||
/*
|
||
* The following structure defines the set of 'volatile' integer registers.
|
||
* These registers need not be preserved by a called C function. Given that
|
||
* they are not preserved across function calls, they must be save/restored
|
||
* (along with the s_coop_reg) when a preemptive context switch occurs.
|
||
*/
|
||
|
||
typedef struct s_preempReg {
|
||
|
||
/*
|
||
* The volatile registers 'eax', 'ecx' and 'edx' area not included in
|
||
*the
|
||
* definition of 'tPreempReg' since the interrupt stubs
|
||
*(_IntEnt/_IntExit)
|
||
* and exception stubs (_ExcEnt/_ExcEnter) use the stack to save and
|
||
* restore the values of these registers in order to support interrupt
|
||
* nesting. The stubs do _not_ copy the saved values from the stack
|
||
*into
|
||
* the TCS.
|
||
*
|
||
* unsigned long eax;
|
||
* unsigned long ecx;
|
||
* unsigned long edx;
|
||
*/
|
||
|
||
} tPreempReg;
|
||
|
||
/*
|
||
* The macro CONFIG_FP_SHARING shall be set to indicate that the
|
||
* saving/restoring of the traditional x87 floating point (and MMX) registers
|
||
* are supported by the nanokernel's context swapping code. The macro
|
||
* CONFIG_SSE shall _also_ be set if saving/restoring of the XMM
|
||
* registers is also supported in the nanokernel's context swapping code.
|
||
*/
|
||
|
||
#ifdef CONFIG_FP_SHARING
|
||
|
||
/* definition of a single x87 (floating point / MMX) register */
|
||
|
||
typedef struct s_FpReg {
|
||
unsigned char reg[10]; /* 80 bits: ST[0-7] */
|
||
} tFpReg;
|
||
|
||
/*
|
||
* The following is the "normal" floating point register save area, or
|
||
* more accurately the save area required by the 'fnsave' and 'frstor'
|
||
* instructions. The structure matches the layout described in the
|
||
* "Intel® 64 and IA-32 Architectures Software Developer’s Manual
|
||
* Volume 1: Basic Architecture": Protected Mode x87 FPU State Image in
|
||
* Memory, 32-Bit Format.
|
||
*/
|
||
|
||
typedef struct s_FpRegSet { /* # of bytes: name of register */
|
||
unsigned short fcw; /* 2 : x87 FPU control word */
|
||
unsigned short pad1; /* 2 : N/A */
|
||
unsigned short fsw; /* 2 : x87 FPU status word */
|
||
unsigned short pad2; /* 2 : N/A */
|
||
unsigned short ftw; /* 2 : x87 FPU tag word */
|
||
unsigned short pad3; /* 2 : N/A */
|
||
unsigned int fpuip; /* 4 : x87 FPU instruction pointer offset */
|
||
unsigned short cs; /* 2 : x87 FPU instruction pointer selector */
|
||
unsigned short fop : 11; /* 2 : x87 FPU opcode */
|
||
unsigned short pad4 : 5; /* : 5 bits = 00000 */
|
||
unsigned int fpudp; /* 4 : x87 FPU instr operand ptr offset */
|
||
unsigned short ds; /* 2 : x87 FPU instr operand ptr selector */
|
||
unsigned short pad5; /* 2 : N/A */
|
||
tFpReg fpReg[8]; /* 80 : ST0 -> ST7 */
|
||
} tFpRegSet __aligned(FP_REG_SET_ALIGN);
|
||
|
||
#ifdef CONFIG_SSE
|
||
|
||
/* definition of a single x87 (floating point / MMX) register */
|
||
|
||
typedef struct s_FpRegEx {
|
||
unsigned char reg[10]; /* 80 bits: ST[0-7] or MM[0-7] */
|
||
unsigned char rsrvd[6]; /* 48 bits: reserved */
|
||
} tFpRegEx;
|
||
|
||
/* definition of a single XMM register */
|
||
|
||
typedef struct s_XmmReg {
|
||
unsigned char reg[16]; /* 128 bits: XMM[0-7] */
|
||
} tXmmReg;
|
||
|
||
/*
|
||
* The following is the "extended" floating point register save area, or
|
||
* more accurately the save area required by the 'fxsave' and 'fxrstor'
|
||
* instructions. The structure matches the layout described in the
|
||
* "Intel 64 and IA-32 Architectures Software Developer's Manual
|
||
* Volume 2A: Instruction Set Reference, A-M", except for the bytes from offset
|
||
* 464 to 511 since these "are available to software use. The processor does
|
||
* not write to bytes 464:511 of an FXSAVE area".
|
||
*
|
||
* This structure must be aligned on a 16 byte boundary when the instructions
|
||
* fxsave/fxrstor are used to write/read the data to/from the structure.
|
||
*/
|
||
|
||
typedef struct s_FpRegSetEx /* # of bytes: name of register */
|
||
{
|
||
unsigned short fcw; /* 2 : x87 FPU control word */
|
||
unsigned short fsw; /* 2 : x87 FPU status word */
|
||
unsigned char ftw; /* 1 : x87 FPU abridged tag word */
|
||
unsigned char rsrvd0; /* 1 : reserved */
|
||
unsigned short fop; /* 2 : x87 FPU opcode */
|
||
unsigned int fpuip; /* 4 : x87 FPU instruction pointer offset */
|
||
unsigned short cs; /* 2 : x87 FPU instruction pointer selector */
|
||
unsigned short rsrvd1; /* 2 : reserved */
|
||
unsigned int fpudp; /* 4 : x87 FPU instr operand ptr offset */
|
||
unsigned short ds; /* 2 : x87 FPU instr operand ptr selector */
|
||
unsigned short rsrvd2; /* 2 : reserved */
|
||
unsigned int mxcsr; /* 4 : MXCSR register state */
|
||
unsigned int mxcsrMask; /* 4 : MXCSR register mask */
|
||
tFpRegEx fpReg[8]; /* 128 : x87 FPU/MMX registers */
|
||
tXmmReg xmmReg[8]; /* 128 : XMM registers */
|
||
unsigned char rsrvd3[176]; /* 176 : reserved */
|
||
} tFpRegSetEx __aligned(FP_REG_SET_ALIGN);
|
||
|
||
#else /* CONFIG_SSE == 0 */
|
||
|
||
typedef struct s_FpRegSetEx {
|
||
} tFpRegSetEx;
|
||
|
||
#endif /* CONFIG_SSE == 0 */
|
||
|
||
#else /* CONFIG_FP_SHARING == 0 */
|
||
|
||
/* empty floating point register definition */
|
||
|
||
typedef struct s_FpRegSet {
|
||
} tFpRegSet;
|
||
|
||
typedef struct s_FpRegSetEx {
|
||
} tFpRegSetEx;
|
||
|
||
#endif /* CONFIG_FP_SHARING == 0 */
|
||
|
||
/*
|
||
* The following structure defines the set of 'non-volatile' x87 FPU/MMX/SSE
|
||
* registers. These registers must be preserved by a called C function.
|
||
* These are the only registers that need to be saved/restored when a
|
||
* cooperative context switch occurs.
|
||
*/
|
||
|
||
typedef struct s_coopFloatReg {
|
||
|
||
/*
|
||
* This structure intentionally left blank, i.e. the ST[0] -> ST[7] and
|
||
* XMM0 -> XMM7 registers are all 'volatile'.
|
||
*/
|
||
|
||
} tCoopFloatReg;
|
||
|
||
/*
|
||
* The following structure defines the set of 'volatile' x87 FPU/MMX/SSE
|
||
* registers. These registers need not be preserved by a called C function.
|
||
* Given that they are not preserved across function calls, they must be
|
||
* save/restored (along with s_coopFloatReg) when a preemptive context
|
||
* switch occurs.
|
||
*/
|
||
|
||
typedef struct s_preempFloatReg {
|
||
union {
|
||
/* threads with USE_FP utilize this format */
|
||
tFpRegSet fpRegs;
|
||
/* threads with USE_SSE utilize this format */
|
||
tFpRegSetEx fpRegsEx;
|
||
} floatRegsUnion;
|
||
} tPreempFloatReg;
|
||
|
||
/*
|
||
* The thread control stucture definition. It contains the
|
||
* various fields to manage a _single_ thread. The TCS will be aligned
|
||
* to the appropriate architecture specific boundary via the
|
||
* _new_thread() call.
|
||
*/
|
||
|
||
struct tcs {
|
||
/*
|
||
* Link to next thread in singly-linked thread list (such as
|
||
* prioritized list of runnable fibers, or list of fibers waiting on a
|
||
* nanokernel FIFO).
|
||
*/
|
||
|
||
struct tcs *link;
|
||
|
||
/*
|
||
* See the above flag definitions above for valid bit settings. This
|
||
* field must remain near the start of struct tcs, specifically
|
||
* before any #ifdef'ed fields since the host tools currently use a
|
||
* fixed
|
||
* offset to read the 'flags' field.
|
||
*/
|
||
|
||
int flags;
|
||
|
||
/*
|
||
* Storage space for integer registers. These must also remain near
|
||
* the start of struct tcs for the same reason mention for
|
||
* 'flags'.
|
||
*/
|
||
|
||
tCoopReg coopReg; /* non-volatile integer register storage */
|
||
tPreempReg preempReg; /* volatile integer register storage */
|
||
|
||
#if defined(CONFIG_THREAD_MONITOR)
|
||
struct tcs *next_thread; /* next item in list of ALL fiber+tasks */
|
||
#endif
|
||
#ifdef CONFIG_GDB_INFO
|
||
void *esfPtr; /* pointer to exception stack frame saved by */
|
||
/* outermost exception wrapper */
|
||
#endif /* CONFIG_GDB_INFO */
|
||
int prio; /* thread priority used to sort linked list */
|
||
#if (defined(CONFIG_FP_SHARING) || defined(CONFIG_GDB_INFO))
|
||
/*
|
||
* Nested exception count to maintain setting of EXC_ACTIVE flag across
|
||
* outermost exception. EXC_ACTIVE is used by _Swap() lazy FP
|
||
* save/restore and by debug tools.
|
||
*/
|
||
unsigned excNestCount; /* nested exception count */
|
||
#endif /* CONFIG_FP_SHARING || CONFIG_GDB_INFO */
|
||
|
||
#ifdef CONFIG_THREAD_CUSTOM_DATA
|
||
void *custom_data; /* available for custom use */
|
||
#endif
|
||
|
||
#ifdef CONFIG_NANO_TIMEOUTS
|
||
struct _nano_timeout nano_timeout;
|
||
#endif
|
||
|
||
/*
|
||
* The location of all floating point related structures/fields MUST be
|
||
* located at the end of struct tcs. This way only the
|
||
* fibers/tasks that actually utilize non-integer capabilities need to
|
||
* account for the increased memory required for storing FP state when
|
||
* sizing stacks.
|
||
*
|
||
* Given that stacks "grow down" on IA-32, and the TCS is located
|
||
* at the start of a thread's "workspace" memory, the stacks of
|
||
* fibers/tasks that do not utilize floating point instruction can
|
||
* effectively consume the memory occupied by the 'tCoopFloatReg' and
|
||
* 'tPreempFloatReg' structures without ill effect.
|
||
*/
|
||
|
||
tCoopFloatReg coopFloatReg; /* non-volatile float register storage */
|
||
tPreempFloatReg preempFloatReg; /* volatile float register storage */
|
||
};
|
||
|
||
/*
|
||
* The nanokernel structure definition. It contains various fields to
|
||
* manage _all_ the threads in the nanokernel (system level).
|
||
*/
|
||
|
||
typedef struct s_NANO {
|
||
struct tcs *fiber; /* singly linked list of runnable fibers */
|
||
struct tcs *task; /* pointer to runnable task */
|
||
struct tcs *current; /* currently scheduled thread (fiber or task) */
|
||
#if defined(CONFIG_THREAD_MONITOR)
|
||
struct tcs *threads; /* singly linked list of ALL fiber+tasks */
|
||
#endif
|
||
unsigned nested; /* nested interrupt count */
|
||
char *common_isp; /* interrupt stack pointer base */
|
||
|
||
#ifdef CONFIG_ADVANCED_POWER_MANAGEMENT
|
||
int32_t idle; /* Number of ticks for kernel idling */
|
||
#endif /* CONFIG_ADVANCED_POWER_MANAGEMENT */
|
||
|
||
|
||
#ifdef CONFIG_FP_SHARING
|
||
/*
|
||
* A 'current_sse' field does not exist in addition to the 'current_fp'
|
||
* field since it's not possible to divide the IA-32 non-integer
|
||
* registers into 2 distinct blocks owned by differing threads. In
|
||
* other words, given that the 'fxnsave/fxrstor' instructions
|
||
* save/restore both the X87 FPU and XMM registers, it's not possible
|
||
* for a thread to only "own" the XMM registers.
|
||
*/
|
||
|
||
struct tcs *current_fp; /* thread (fiber or task) that owns the FP regs */
|
||
#endif /* CONFIG_FP_SHARING */
|
||
#ifdef CONFIG_NANO_TIMEOUTS
|
||
sys_dlist_t timeout_q;
|
||
#endif
|
||
} tNANO;
|
||
|
||
/* stack alignment related macros: STACK_ALIGN_SIZE is defined above */
|
||
|
||
#define STACK_ROUND_UP(x) ROUND_UP(x, STACK_ALIGN_SIZE)
|
||
#define STACK_ROUND_DOWN(x) ROUND_DOWN(x, STACK_ALIGN_SIZE)
|
||
|
||
/* variable declarations */
|
||
|
||
/*
|
||
* There is only a single instance of the s_NANO structure, given that there
|
||
* is only a single nanokernel in the system: _nanokernel
|
||
*/
|
||
|
||
extern tNANO _nanokernel;
|
||
|
||
/*
|
||
* _interrupt_vectors_allocated[] is generated by the 'gen_idt' tool. It is
|
||
* initialized to identify which interrupts have been statically connected
|
||
* and which interrupts are available to be dynamically connected at run time.
|
||
* The variable itself is defined in the linker file.
|
||
*/
|
||
|
||
extern unsigned int _interrupt_vectors_allocated[];
|
||
|
||
/* inline function definitions */
|
||
|
||
/**
|
||
*
|
||
* @brief Performs architecture-specific initialization
|
||
*
|
||
* This routine performs architecture-specific initialization of the nanokernel.
|
||
* Trivial stuff is done inline; more complex initialization is done via
|
||
* function calls.
|
||
*
|
||
* @return N/A
|
||
*/
|
||
static inline void nanoArchInit(void)
|
||
{
|
||
extern void *__isr___SpuriousIntHandler;
|
||
extern void *_dummy_spurious_interrupt;
|
||
extern void *_dummy_exception_vector_stub;
|
||
extern char _interrupt_stack[CONFIG_ISR_STACK_SIZE];
|
||
extern void _ExcEnt(void);
|
||
|
||
_nanokernel.nested = 0;
|
||
|
||
_nanokernel.common_isp = (char *)STACK_ROUND_DOWN(
|
||
&_interrupt_stack[CONFIG_ISR_STACK_SIZE - 1]);
|
||
/*
|
||
* Forces the inclusion of the spurious interrupt handlers. If a
|
||
* reference isn't made then intconnect.o is never pulled in by the
|
||
* linker.
|
||
*/
|
||
|
||
_dummy_spurious_interrupt = &__isr___SpuriousIntHandler;
|
||
|
||
/*
|
||
* Forces the inclusion of the exception vector stub code. If a
|
||
* reference isn't made then excstubs.o is never pulled in by the
|
||
* linker.
|
||
*/
|
||
|
||
_dummy_exception_vector_stub = &_ExcEnt;
|
||
|
||
|
||
}
|
||
|
||
/**
|
||
*
|
||
* @brief Set the return value for the specified fiber (inline)
|
||
*
|
||
* @param fiber pointer to fiber
|
||
* @param value value to set as return value
|
||
*
|
||
* The register used to store the return value from a function call invocation
|
||
* is set to <value>. It is assumed that the specified <fiber> is pending, and
|
||
* thus the fibers context is stored in its TCS.
|
||
*
|
||
* @return N/A
|
||
*/
|
||
static inline void fiberRtnValueSet(struct tcs *fiber, unsigned int value)
|
||
{
|
||
/* write into 'eax' slot created in _Swap() entry */
|
||
|
||
*(unsigned int *)(fiber->coopReg.esp) = value;
|
||
}
|
||
|
||
/* definitions to support nanoCpuExcConnect() */
|
||
|
||
#define _EXC_STUB_SIZE 0x14
|
||
|
||
/* function prototypes */
|
||
|
||
extern void nano_cpu_atomic_idle(unsigned int imask);
|
||
|
||
extern void nanoCpuExcConnect(unsigned int vector,
|
||
void (*routine)(NANO_ESF *pEsf));
|
||
|
||
extern void _IntVecSet(unsigned int vector,
|
||
void (*routine)(void *),
|
||
unsigned int dpl);
|
||
|
||
extern void _MsrWrite(unsigned int msr, uint64_t msrData);
|
||
extern uint64_t _MsrRead(unsigned int msr);
|
||
|
||
/*
|
||
* _IntLibInit() is called from the non-arch specific nanokernel function,
|
||
* _nano_init(). The IA-32 nanokernel does not require any special
|
||
* initialization of the interrupt subsystem. However, we still need to
|
||
* provide an _IntLibInit() of some sort to prevent build errors.
|
||
*/
|
||
static inline void _IntLibInit(void)
|
||
{
|
||
}
|
||
|
||
int _stub_alloc(unsigned int *ep, unsigned int limit);
|
||
void *_get_dynamic_stub(int stub_idx, void *base_ptr);
|
||
uint8_t _stub_idx_from_vector(int vector);
|
||
|
||
/* the _idt_base_address symbol is generated via a linker script */
|
||
extern unsigned char _idt_base_address[];
|
||
|
||
#include <stddef.h> /* For size_t */
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#define _IS_IN_ISR() (_nanokernel.nested != 0)
|
||
|
||
#endif /* _ASMLANGUAGE */
|
||
|
||
#endif /* _NANO_PRIVATE_H */
|