🔧 使cpu支持SSE(目前会出现#GP)

This commit is contained in:
fslongjin 2022-01-27 14:58:14 +08:00
parent ae52d9c2d2
commit 40a551d154
9 changed files with 198 additions and 16 deletions

View File

@ -545,6 +545,7 @@ Label_Set_SVGA_Mode:
mov eax, cr0
or eax, 1 ; 启用保护模式
or eax, 0x22 ; 启用x87浮点运算单元
mov cr0, eax
; 跳转到保护模式下的第一个程序
@ -632,6 +633,15 @@ GO_TO_TMP_Protect:
bts eax, 31 ; 开启分页管理机制
mov cr0, eax
;now enable SSE and the like
mov eax, cr0
and ax, 0xFFFB ;clear coprocessor emulation CR0.EM
or ax, 0x2 ;set coprocessor monitoring CR0.MP
mov cr0, eax
mov eax, cr4
or ax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, eax
; === 通过此条远跳转指令处理器跳转到内核文件进行执行正式进入IA-32e模式

View File

@ -1,14 +1,17 @@
SUBDIR_ROOTS := . common
DIRS := . $(shell find $(SUBDIR_ROOTS) -type d)
GARBAGE_PATTERNS := *.o *.s~ *.s *.S~ *.c~ *.h~ kernel *.a
GARBAGE_PATTERNS := *.o *.s~ *.s *.S~ *.c~ *.h~ kernel
GARBAGE := $(foreach DIR,$(DIRS),$(addprefix $(DIR)/,$(GARBAGE_PATTERNS)))
DIR_LIB=lib
lib_patterns := *.a
LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns)))
all: kernel
objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary kernel ../bin/kernel/kernel.bin
kernel: head.o entry.o main.o printk.o trap.o
ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o -T link.lds
kernel: head.o entry.o main.o printk.o trap.o mm.o
ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o mm/mm.o -T link.lds
head.o: head.S
gcc -E head.S > head.s # 预处理
@ -21,14 +24,17 @@ entry.o: exception/entry.S
main.o: main.c
# -fno-builtin: 不使用C语言内建函数
# The -m64 option sets int to 32bits and long and pointer to 64 bits and generates code for AMDs x86-64 architecture.
gcc -mcmodel=large -fno-builtin -m64 -c main.c -o main.o -fno-stack-protector
gcc -mcmodel=large -fno-builtin -m64 -c main.c -o main.o
printk.o: common/printk.c
gcc -mcmodel=large -fno-builtin -m64 -c common/printk.c -o common/printk.o -fno-stack-protector
gcc -mcmodel=large -fno-builtin -m64 -c common/printk.c -o common/printk.o
trap.o: exception/trap.c
gcc -mcmodel=large -fno-builtin -m64 -c exception/trap.c -o exception/trap.o -fno-stack-protector
gcc -mcmodel=large -fno-builtin -m64 -c exception/trap.c -o exception/trap.o
mm.o: mm/mm.c
gcc -mcmodel=large -fno-builtin -m64 -c mm/mm.c -o mm/mm.o
clean:
rm -rf $(GARBAGE)

View File

@ -24,13 +24,20 @@
#define io_lfence() __asm__ __volatile__("lfence\n\t" :: \
: "memory") // 在lfence指令前的读操作当必须在lfence指令后的读操作前完成。
#define ABS(x) ((x) > 0 ? (x) : -(x)) // 绝对值
// 定义类型的缩写
typedef unsigned long ul;
typedef unsigned long long ull;
typedef long long ll;
#define ABS(x) ((x) > 0 ? (x) : -(x)) // 绝对值
// 四舍五入成整数
ul round(double x)
{
return (ul)(x+0.5);
}
//链表数据结构
struct List
{

View File

@ -2,7 +2,6 @@
// Created by longjin on 2022/1/22.
//
#include "printk.h"
#include <math.h>
//#include "linkage.h"
struct screen_info pos;
@ -351,6 +350,18 @@ static int vsprintf(char *buf, const char *fmt, va_list args)
*ip = str - buf;
break;
case 'f':
// 默认精度为3
//printk("1111\n");
//va_arg(args, double);
//printk("222\n");
if (precision < 0)
precision = 3;
str = write_float_point_num(str, va_arg(args, double), field_width, precision, flags);
break;
//对于不识别的控制符,直接输出
default:
@ -460,7 +471,98 @@ static char *write_num(char *str, long long num, int base, int field_width, int
while (js_num-- > 0)
*str++ = tmp_num[js_num];
while (field_width-- > 0)
*str++ = ' ';
return str;
}
static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags)
{
/**
* @brief
*
* @param str
* @param num
* @param field_width
* @param precision
* @param flags
*/
char pad, sign, tmp_num_z[100], tmp_num_d[350];
const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// 显示小写字母
if (flags & SMALL)
digits = "0123456789abcdefghijklmnopqrstuvwxyz";
// 设置填充元素
pad = (flags & PAD_ZERO) ? '0' : ' ';
sign = 0;
if (flags & SIGN && num < 0)
{
sign = '-';
num = -num;
}
else
{
// 设置符号
sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0);
}
// sign占用了一个宽度
if (sign)
--field_width;
int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度
ul num_z = (ul)(num); // 获取整数部分
ul num_decimal = (ul)(round((num - num_z) * precision)); // 获取小数部分
if (num == 0)
tmp_num_z[js_num_z++] = '0';
else
{
//存储整数部分
while (num_z > 0)
{
tmp_num_z[js_num_z++] = digits[num_z % 10]; // 注意这里,输出的数字,是小端对齐的。低位存低位
num_z /= 10;
}
}
while (num_decimal > 0)
{
tmp_num_d[js_num_d++] = digits[num_decimal % 10];
num_decimal /= 10;
}
field_width -= (precision + 1 + js_num_z);
// 靠右对齐
if (!(flags & LEFT))
while (field_width-- > 0)
*str++ = pad;
if (sign)
*str++ = sign;
// 输出整数部分
while (js_num_z-- > 0)
*str++ = tmp_num_z[js_num_z];
*str++ = '.';
// 输出小数部分
while (js_num_d-- > 0)
*str++ = tmp_num_d[js_num_d];
while (js_num_d < precision)
{
--precision;
*str++ = '0';
}
while (field_width-- > 0)
*str++ = ' ';

View File

@ -94,6 +94,9 @@ static int vsprintf(char *buf, const char *fmt, va_list args);
*/
static char* write_num(char *str, long long num, int base, int field_width, int precision, int flags);
static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags);
/**
* @brief
*

View File

@ -211,7 +211,7 @@ void do_general_protection(unsigned long rsp, unsigned long error_code)
printk("[ ");
printk_color(RED, BLACK, "ERROR");
printk(" ] do_general_protection(13),\tError Code:%#18lx,\tRSP:%#18lx,\tRIP:%#18lx\n", error_code, rsp, *rip);
return;
while (1)
;
}

View File

@ -6,8 +6,10 @@
#include "common/printk.h"
#include "exception/gate.h"
#include "exception/trap.h"
#include "mm/mm.h"
int *FR_address = (int *)0xffff800000a00000; //帧缓存区的地址
char fxsave_region[512] __attribute__((aligned(16)));
void show_welcome()
{
@ -67,11 +69,16 @@ void init()
// 初始化任务状态段表
ul tss_item_addr = 0xffff800000007c00;
set_TSS64(tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr,
tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr);
tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr);
// 初始化中断描述符表
init_sys_vector();
asm volatile(" fxsave %0 " ::"m"(fxsave_region));
// 初始化内存管理单元
printk("[ DragonOS ] Initializing memory manage unit...\n");
mm_init();
}
//操作系统内核从这里开始执行
void Start_Kernel(void)
@ -80,13 +87,10 @@ void Start_Kernel(void)
init();
show_welcome();
//test_printk();
//int t = 1 / 0; // 测试异常处理模块能否正常工作 触发除法错误
int t = *(int*) 0xffff80000aa00000; // 触发页故障
// int t = *(int *)0xffff80000aa00000; // 触发页故障
while (1)
;

29
kernel/mm/mm.c Normal file
View File

@ -0,0 +1,29 @@
#include "mm.h"
#include "../common/printk.h"
ul Total_Memory = 0;
void mm_init()
{
// 实模式下获取到的信息的起始地址转换为ARDS指针
struct ARDS *ards_ptr = (struct ARDS *)0xffff800000007e00;
for (int i = 0; i < 32; ++i)
{
printk("Addr = %#10lx,%8lx\tLength = %#10lx,%8lx\tType = %#10lx\n",
ards_ptr->BaseAddrH, ards_ptr->BaseAddrL, ards_ptr->LengthH, ards_ptr->LengthL, ards_ptr->type);
//可用的内存
if (ards_ptr->type == 1)
{
Total_Memory += ards_ptr->LengthL;
Total_Memory += ((ul)(ards_ptr->LengthH)) << 32;
}
++ards_ptr;
// 脏数据
if (ards_ptr->type > 4)
break;
}
printk_color(ORANGE, BLACK, "Total amount of RAM DragonOS can use: %ld bytes\n", Total_Memory);
}

21
kernel/mm/mm.h Normal file
View File

@ -0,0 +1,21 @@
#pragma once
#include"../common/glib.h"
// Address Range Descriptor Structure 地址范围描述符
struct ARDS
{
unsigned int BaseAddrL; // 基地址低32位
unsigned int BaseAddrH; // 基地址高32位
unsigned int LengthL; // 内存长度低32位 以字节为单位
unsigned int LengthH; // 内存长度高32位
unsigned int type; // 本段内存的类型
// type=1 表示可以被操作系统使用
// type=2 ARR - 内存使用中或被保留,操作系统不能使用
// 其他 未定义操作系统需要将其视为ARR
};
void mm_init();