mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-09 19:36:47 +00:00
🆕 测定tsc频率
This commit is contained in:
parent
72b67ddf1c
commit
4bc64de8f9
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -112,7 +112,8 @@
|
||||
"time.h": "c",
|
||||
"ia64_msi.h": "c",
|
||||
"errno.h": "c",
|
||||
"bug.h": "c"
|
||||
"bug.h": "c",
|
||||
"apic_timer.h": "c"
|
||||
},
|
||||
"C_Cpp.errorSquiggles": "Enabled",
|
||||
"esbonio.sphinx.confDir": ""
|
||||
|
@ -26,6 +26,8 @@ uint Cpu_Processor_Type;
|
||||
uint Cpu_max_phys_addrline_size;
|
||||
// 处理器支持的最大线性地址可寻址地址线宽度
|
||||
uint Cpu_max_linear_addrline_size;
|
||||
// 处理器的tsc频率(单位:hz)(HPET定时器在测定apic频率时,顺便测定了这个值)
|
||||
uint64_t Cpu_tsc_freq = 0;
|
||||
|
||||
struct cpu_core_info_t cpu_core_info[MAX_CPU_NUM];
|
||||
void cpu_init(void)
|
||||
@ -115,6 +117,6 @@ uint32_t cpu_get_core_crysral_freq()
|
||||
: "0"(0x15), "2"(0)
|
||||
: "memory");
|
||||
// kdebug("Cpu_cpuid_max_Basic_mop = %#03x, a=%ld, b=%ld, c=%ld, d=%ld", Cpu_cpuid_max_Basic_mop, a, b, c, d);
|
||||
|
||||
|
||||
return c;
|
||||
}
|
@ -29,39 +29,41 @@ extern uint32_t Cpu_max_phys_addrline_size;
|
||||
// 处理器支持的最大线性地址可寻址地址线宽度
|
||||
extern uint32_t Cpu_max_linear_addrline_size;
|
||||
|
||||
// 处理器的tsc频率(单位:hz)(HPET定时器在测定apic频率时,顺便测定了这个值)
|
||||
extern uint64_t Cpu_tsc_freq;
|
||||
|
||||
/**
|
||||
* @brief 执行cpuid指令
|
||||
*
|
||||
*
|
||||
* @param mop 主功能号
|
||||
* @param sop 子功能号
|
||||
* @param eax 结果的eax值
|
||||
* @param ebx 结果的ebx值
|
||||
* @param ecx 结果的ecx值
|
||||
* @param edx 结果的edx值
|
||||
*
|
||||
*
|
||||
* cpuid指令参考英特尔开发手册卷2A Chapter3 3.2 Instruction
|
||||
*/
|
||||
void cpu_cpuid(uint32_t mop, uint32_t sop, uint32_t *eax, uint32_t*ebx, uint32_t*ecx, uint32_t*edx);
|
||||
void cpu_cpuid(uint32_t mop, uint32_t sop, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
|
||||
|
||||
/**
|
||||
* @brief 初始化获取处理器信息模块
|
||||
*
|
||||
*
|
||||
*/
|
||||
void cpu_init(void);
|
||||
|
||||
struct cpu_core_info_t
|
||||
{
|
||||
uint64_t stack_start; // 栈基地址
|
||||
uint64_t ist_stack_start; // IST栈基地址
|
||||
uint64_t tss_vaddr; // tss地址
|
||||
uint64_t stack_start; // 栈基地址
|
||||
uint64_t ist_stack_start; // IST栈基地址
|
||||
uint64_t tss_vaddr; // tss地址
|
||||
};
|
||||
|
||||
extern struct cpu_core_info_t cpu_core_info[MAX_CPU_NUM];
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取当前cpu核心晶振频率
|
||||
*
|
||||
*
|
||||
* @return uint32_t 当前cpu核心晶振频率
|
||||
*/
|
||||
uint32_t cpu_get_core_crysral_freq();
|
@ -10,6 +10,7 @@
|
||||
#include <stdint.h>
|
||||
#include <common/stddef.h>
|
||||
#include <arch/arch.h>
|
||||
#include <common/compiler.h>
|
||||
|
||||
#define sti() __asm__ __volatile__("sti\n\t" :: \
|
||||
: "memory") //开启外部中断
|
||||
@ -27,6 +28,13 @@
|
||||
#define io_lfence() __asm__ __volatile__("lfence\n\t" :: \
|
||||
: "memory") // 在lfence指令前的读操作必须在lfence指令后的读操作前完成。
|
||||
|
||||
#define rdtsc() ({ \
|
||||
uint64_t tmp1 = 0, tmp2 = 0; \
|
||||
asm volatile("rdtsc" \
|
||||
: "=d"(tmp1), "=a"(tmp2)::"memory"); \
|
||||
(tmp1 << 32 | tmp2); \
|
||||
})
|
||||
|
||||
/**
|
||||
* @brief 根据结构体变量内某个成员变量member的基地址,计算出该结构体变量的基地址
|
||||
* @param ptr 指向结构体变量内的成员变量member的指针
|
||||
@ -170,7 +178,7 @@ static inline struct List *list_next(struct List *entry)
|
||||
//计算字符串的长度(经过测试,该版本比采用repne/scasb汇编的运行速度快16.8%左右)
|
||||
static inline int strlen(const char *s)
|
||||
{
|
||||
if(s == NULL)
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
register int __res = 0;
|
||||
while (s[__res] != '\0')
|
||||
@ -182,10 +190,10 @@ static inline int strlen(const char *s)
|
||||
|
||||
/**
|
||||
* @brief 测量字符串的长度
|
||||
*
|
||||
*
|
||||
* @param src 字符串
|
||||
* @param maxlen 最大长度
|
||||
* @return long
|
||||
* @return long
|
||||
*/
|
||||
long strnlen(const char *src, unsigned long maxlen);
|
||||
|
||||
@ -213,14 +221,14 @@ void *memset(void *dst, unsigned char C, ul size)
|
||||
return dst;
|
||||
}
|
||||
|
||||
void *memset_c(void* dst, uint8_t c, size_t count)
|
||||
void *memset_c(void *dst, uint8_t c, size_t count)
|
||||
{
|
||||
uint8_t* xs = (uint8_t*)dst;
|
||||
|
||||
while (count--)
|
||||
*xs++ = c;
|
||||
|
||||
return dst;
|
||||
uint8_t *xs = (uint8_t *)dst;
|
||||
|
||||
while (count--)
|
||||
*xs++ = c;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,7 +241,7 @@ void *memset_c(void* dst, uint8_t c, size_t count)
|
||||
*/
|
||||
static void *memcpy(void *dst, const void *src, long Num)
|
||||
{
|
||||
int d0=0, d1=0, d2=0;
|
||||
int d0 = 0, d1 = 0, d2 = 0;
|
||||
__asm__ __volatile__("cld \n\t"
|
||||
"rep \n\t"
|
||||
"movsq \n\t"
|
||||
@ -283,7 +291,6 @@ int strcmp(char *FirstPart, char *SecondPart)
|
||||
return __res;
|
||||
}
|
||||
|
||||
|
||||
// 从io口读入8个bit
|
||||
unsigned char io_in8(unsigned short port)
|
||||
{
|
||||
|
@ -18,7 +18,13 @@ static uint32_t HPET_COUNTER_CLK_PERIOD = 0; // 主计数器时间精度(单
|
||||
static double HPET_freq = 0; // 主计时器频率
|
||||
static uint8_t HPET_NUM_TIM_CAP = 0; // 定时器数量
|
||||
static char measure_apic_timer_flag; // 初始化apic时钟时所用到的标志变量
|
||||
extern struct rtc_time_t rtc_now; // 导出全局墙上时钟
|
||||
|
||||
// 测定tsc频率的临时变量
|
||||
static uint64_t test_tsc_start = 0;
|
||||
static uint64_t test_tsc_end = 0;
|
||||
extern uint64_t Cpu_tsc_freq; // 导出自cpu.c
|
||||
|
||||
extern struct rtc_time_t rtc_now; // 导出全局墙上时钟
|
||||
|
||||
enum
|
||||
{
|
||||
@ -91,11 +97,12 @@ void HPET_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测量apic定时器频率的中断回调函数
|
||||
* @brief 测定apic定时器以及tsc的频率的中断回调函数
|
||||
*
|
||||
*/
|
||||
void HPET_measure_apic_timer_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
|
||||
void HPET_measure_handler(uint64_t number, uint64_t param, struct pt_regs *regs)
|
||||
{
|
||||
test_tsc_end = rdtsc();
|
||||
// 停止apic定时器
|
||||
// 写入每1ms的ticks
|
||||
apic_timer_stop();
|
||||
@ -104,10 +111,10 @@ void HPET_measure_apic_timer_handler(uint64_t number, uint64_t param, struct pt_
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 测定apic定时器的频率
|
||||
* @brief 测定apic定时器以及tsc的频率
|
||||
*
|
||||
*/
|
||||
void HPET_measure_apic_timer_freq()
|
||||
void HPET_measure_freq()
|
||||
{
|
||||
kinfo("Measuring local APIC timer's frequency...");
|
||||
const uint64_t interval = APIC_TIMER_INTERVAL; // 测量给定时间内的计数
|
||||
@ -136,7 +143,7 @@ void HPET_measure_apic_timer_freq()
|
||||
measure_apic_timer_flag = false;
|
||||
|
||||
// 注册中断
|
||||
irq_register(34, &entry, &HPET_measure_apic_timer_handler, 0, &HPET_intr_controller, "HPET0 measure");
|
||||
irq_register(34, &entry, &HPET_measure_handler, 0, &HPET_intr_controller, "HPET0 measure");
|
||||
|
||||
// 设置div16
|
||||
apic_timer_stop();
|
||||
@ -148,6 +155,8 @@ void HPET_measure_apic_timer_freq()
|
||||
// 启动apic定时器
|
||||
apic_timer_set_LVT(151, 0, APIC_LVT_Timer_One_Shot);
|
||||
*(uint64_t *)(HPET_REG_BASE + GEN_CONF) = 3; // 置位旧设备中断路由兼容标志位、定时器组使能标志位,开始计时
|
||||
// 顺便测定tsc频率
|
||||
test_tsc_start = rdtsc();
|
||||
io_mfence();
|
||||
|
||||
while (measure_apic_timer_flag == false)
|
||||
@ -158,6 +167,10 @@ void HPET_measure_apic_timer_freq()
|
||||
*(uint64_t *)(HPET_REG_BASE + GEN_CONF) = 0; // 停用HPET定时器
|
||||
io_mfence();
|
||||
kinfo("Local APIC timer's freq: %d ticks/ms.", apic_timer_ticks_result);
|
||||
// 计算tsc频率
|
||||
Cpu_tsc_freq = (test_tsc_end - test_tsc_start) * (1000UL / interval);
|
||||
|
||||
kinfo("TSC frequency: %ldMHz", Cpu_tsc_freq / 1000000);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -10,10 +10,10 @@
|
||||
int HPET_init();
|
||||
|
||||
/**
|
||||
* @brief 测定apic定时器的频率
|
||||
* @brief 测定apic定时器以及tsc的频率
|
||||
*
|
||||
*/
|
||||
void HPET_measure_apic_timer_freq();
|
||||
void HPET_measure_freq();
|
||||
|
||||
/**
|
||||
* @brief 启用HPET周期中断(5ms)
|
||||
|
@ -144,7 +144,7 @@ void system_initialize()
|
||||
|
||||
// process_init();
|
||||
HPET_init();
|
||||
HPET_measure_apic_timer_freq();
|
||||
HPET_measure_freq();
|
||||
// current_pcb->preempt_count = 0;
|
||||
// kdebug("cpu_get_core_crysral_freq()=%ld", cpu_get_core_crysral_freq());
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user