新增rust ffi (#77)

* 引入cargo

* 取消对Cargo.lock的跟踪

* 解决vscode报错问题

* new: rust的代码能够调用c语言的printk_color

* 1、将原本run.sh的工作拆解,变为几个不同的make命令
2、在docker镜像中编译rust

* 更改workflow

* update workflow

* new: 解决workflow无法通过编译的问题
This commit is contained in:
login
2022-11-11 15:35:37 +08:00
committed by GitHub
parent 5e023cf791
commit 2813126e31
271 changed files with 609 additions and 307 deletions

17
kernel/src/arch/Makefile Normal file
View File

@ -0,0 +1,17 @@
CFLAGS += -I .
ifeq ($(ARCH), __x86_64__)
kernel_arch_subdirs:=x86_64
endif
all:
@list='$(kernel_arch_subdirs)'; for subdir in $$list; do \
echo "make all in $$subdir";\
cd $$subdir;\
$(MAKE) all CFLAGS="$(CFLAGS)" PIC="$(PIC)";\
cd ..;\
done
clean:
echo "Done."

12
kernel/src/arch/arch.h Normal file
View File

@ -0,0 +1,12 @@
#pragma once
#define ARCH(arch) (defined(AK_ARCH_##arch) && AK_ARCH_##arch)
#ifdef __i386__
# define AK_ARCH_I386 1
#endif
#ifdef __x86_64__
# define AK_ARCH_X86_64 1
#endif

View File

@ -0,0 +1,10 @@
CFLAGS += -I .
all: x86_64_ipi.o ia64_msi.o
x86_64_ipi.o: x86_64_ipi.c
$(CC) $(CFLAGS) -c x86_64_ipi.c -o x86_64_ipi.o
ia64_msi.o: ia64_msi.c
$(CC) $(CFLAGS) -c ia64_msi.c -o ia64_msi.o

View File

@ -0,0 +1,149 @@
#pragma once
#include <stdint.h>
#define sti() __asm__ __volatile__("sti\n\t" :: \
: "memory") //开启外部中断
#define cli() __asm__ __volatile__("cli\n\t" :: \
: "memory") //关闭外部中断
#define nop() __asm__ __volatile__("nop\n\t")
#define hlt() __asm__ __volatile__("hlt\n\t")
#define pause() asm volatile("pause\n\t"); // 处理器等待一段时间
//内存屏障
#define io_mfence() __asm__ __volatile__("mfence\n\t" :: \
: "memory") // 在mfence指令前的读写操作必须在mfence指令后的读写操作前完成。
#define io_sfence() __asm__ __volatile__("sfence\n\t" :: \
: "memory") // 在sfence指令前的写操作必须在sfence指令后的写操作前完成
#define io_lfence() __asm__ __volatile__("lfence\n\t" :: \
: "memory") // 在lfence指令前的读操作必须在lfence指令后的读操作前完成。
/*
* Macros to generate condition code outputs from inline assembly,
* The output operand must be type "bool".
*/
// 如果编译器支持输出标志寄存器值到变量的话则会定义__GCC_ASM_FLAG_OUTPUTS__
#ifdef __GCC_ASM_FLAG_OUTPUTS__
// CC_SET(c)则是用于设置标志寄存器中的某一位
#define CC_SET(c) "\n\t/* output condition code " #c "*/\n"
// "=@cccond"的用法是将标志寄存器中的cond也就是指令集定义的标准条件的值输出到变量中
#define CC_OUT(c) "=@cc" #c
#else
#define CC_SET(c) "\n\tset" #c " %[_cc_" #c "]\n"
#define CC_OUT(c) [_cc_##c] "=qm"
#endif
#define rdtsc() ({ \
uint64_t tmp1 = 0, tmp2 = 0; \
asm volatile("rdtsc" \
: "=d"(tmp1), "=a"(tmp2)::"memory"); \
(tmp1 << 32 | tmp2); \
})
/**
* @brief 读取rsp寄存器的值存储了页目录的基地址
*
* @return unsigned* rsp的值的指针
*/
unsigned long *get_rsp()
{
uint64_t *tmp;
__asm__ __volatile__(
"movq %%rsp, %0\n\t"
: "=r"(tmp)::"memory");
return tmp;
}
/**
* @brief 读取rbp寄存器的值存储了页目录的基地址
*
* @return unsigned* rbp的值的指针
*/
unsigned long *get_rbp()
{
uint64_t *tmp;
__asm__ __volatile__(
"movq %%rbp, %0\n\t"
: "=r"(tmp)::"memory");
return tmp;
}
/**
* @brief 读取ds寄存器的值存储了页目录的基地址
*
* @return unsigned* ds的值的指针
*/
unsigned long *get_ds()
{
uint64_t *tmp;
__asm__ __volatile__(
"movq %%ds, %0\n\t"
: "=r"(tmp)::"memory");
return tmp;
}
/**
* @brief 读取rax寄存器的值存储了页目录的基地址
*
* @return unsigned* rax的值的指针
*/
unsigned long *get_rax()
{
uint64_t *tmp;
__asm__ __volatile__(
"movq %%rax, %0\n\t"
: "=r"(tmp)::"memory");
return tmp;
}
/**
* @brief 读取rbx寄存器的值存储了页目录的基地址
*
* @return unsigned* rbx的值的指针
*/
unsigned long *get_rbx()
{
uint64_t *tmp;
__asm__ __volatile__(
"movq %%rbx, %0\n\t"
: "=r"(tmp)::"memory");
return tmp;
}
// ========= MSR寄存器组操作 =============
/**
* @brief 向msr寄存器组的address处的寄存器写入值value
*
* @param address 地址
* @param value 要写入的值
*/
void wrmsr(uint64_t address, uint64_t value)
{
__asm__ __volatile__("wrmsr \n\t" ::"d"(value >> 32), "a"(value & 0xffffffff), "c"(address)
: "memory");
}
/**
* @brief 从msr寄存器组的address地址处读取值
* rdmsr返回高32bits在edx低32bits在eax
* @param address 地址
* @return uint64_t address处的寄存器的值
*/
uint64_t rdmsr(uint64_t address)
{
unsigned int tmp0, tmp1;
__asm__ __volatile__("rdmsr \n\t"
: "=d"(tmp0), "=a"(tmp1)
: "c"(address)
: "memory");
return ((uint64_t)tmp0 << 32) | tmp1;
}
uint64_t get_rflags()
{
unsigned long tmp = 0;
__asm__ __volatile__("pushfq \n\t"
"movq (%%rsp), %0 \n\t"
"popfq \n\t"
: "=r"(tmp)::"memory");
return tmp;
}

View File

@ -0,0 +1,81 @@
#pragma once
#include <common/compiler.h>
#include <arch/x86_64/asm/asm.h>
/**
* @brief 通过extern不存在的函数来让编译器报错。以防止不符合要求的代码的产生。
*/
extern void __cmpxchg_wrong_size(void) __compiletime_error("Bad argument size for cmpxchg");
// 定义常量:操作符涉及到的字节数
#define __X86_CASE_B 1
#define __X86_CASE_W 2
#define __X86_CASE_L 4
#define __X86_CASE_Q 8
/**
* @brief lock cmpxchg指令的包装。
* 将_ptr指向的值与old_ptr指向的值做比较如果相等则将_new指向的值加载到_ptr指向的值中。
*/
#define __raw_try_cmpxchg(_ptr, _old_ptr, _new, size) \
({ \
bool is_success = false; \
typeof(_ptr) _old = (typeof(_ptr))(_old_ptr); \
typeof(*(_ptr)) __old = *_old; \
typeof(*(_ptr)) __new = (_new); \
switch (size) \
{ \
case __X86_CASE_B: \
{ \
volatile uint8_t *__ptr = (volatile uint8_t *)(_ptr); \
asm volatile("lock cmpxchgb %[new], %[ptr]\n\t" \
: CC_OUT(z)(is_success), \
[ptr] "+m"(*__ptr), \
[old] "+a"(__old) \
: [new] "q"(__new) \
: "memory"); \
break; \
} \
case __X86_CASE_W: \
{ \
volatile uint16_t *__ptr = (volatile uint16_t *)(_ptr); \
asm volatile("lock cmpxchgw %[new], %[ptr]\n\t" \
: CC_OUT(z)(is_success), \
[ptr] "+m"(*__ptr), \
[old] "+a"(__old) \
: [new] "q"(__new) \
: "memory"); \
break; \
} \
case __X86_CASE_L: \
{ \
volatile uint32_t *__ptr = (volatile uint32_t *)(_ptr); \
asm volatile("lock cmpxchgl %[new], %[ptr]\n\t" \
: CC_OUT(z)(is_success), \
[ptr] "+m"(*__ptr), \
[old] "+a"(__old) \
: [new] "q"(__new) \
: "memory"); \
break; \
} \
case __X86_CASE_Q: \
{ \
volatile uint64_t *__ptr = (volatile uint64_t *)(_ptr); \
asm volatile("lock cmpxchgq %[new], %[ptr]\n\t" \
: CC_OUT(z)(is_success), \
[ptr] "+m"(*__ptr), \
[old] "+a"(__old) \
: [new] "q"(__new) \
: "memory"); \
break; \
} \
default: \
__cmpxchg_wrong_size(); \
} \
if (unlikely(is_success == false)) \
*_old = __old; \
likely(is_success); \
})
#define arch_try_cmpxchg(ptr, old_ptr, new_ptr) \
__raw_try_cmpxchg((ptr), (old_ptr), (new_ptr), sizeof(*ptr))

View File

@ -0,0 +1,20 @@
#pragma once
#include <common/glib.h>
#pragma GCC push_options
#pragma GCC optimize("O0")
struct process_control_block;
// 获取当前的pcb
struct process_control_block *get_current_pcb()
{
struct process_control_block *current = NULL;
// 利用了当前pcb和栈空间总大小为32k大小对齐将rsp低15位清空即可获得pcb的起始地址
barrier();
__asm__ __volatile__("andq %%rsp, %0 \n\t"
: "=r"(current)
: "0"(~32767UL));
barrier();
return current;
};
#define current_pcb get_current_pcb()
#pragma GCC pop_options

View File

@ -0,0 +1,28 @@
#include "ia64_msi.h"
/**
* @brief 生成架构相关的msi的message address
*
*/
#define ia64_pci_get_arch_msi_message_address(processor) ((0xfee00000UL | (processor << 12)))
/**
* @brief 生成架构相关的message data
*
*/
#define ia64_pci_get_arch_msi_message_data(vector, processor, edge_trigger, assert) ((uint32_t)((vector & 0xff) | (edge_trigger == 1 ? 0 : (1 << 15)) | ((assert == 0) ? 0 : (1 << 14))))
/**
* @brief 生成msi消息
*
* @param msi_desc msi描述符
* @return struct msi_msg_t* msi消息指针在描述符内
*/
struct msi_msg_t *msi_arch_get_msg(struct msi_desc_t *msi_desc)
{
msi_desc->msg.address_hi = 0;
msi_desc->msg.address_lo = ia64_pci_get_arch_msi_message_address(msi_desc->processor);
msi_desc->msg.data = ia64_pci_get_arch_msi_message_data(msi_desc->irq_num, msi_desc->processor, msi_desc->edge_trigger, msi_desc->assert);
msi_desc->msg.vector_control = 0;
return &(msi_desc->msg);
}

View File

@ -0,0 +1,11 @@
#pragma once
#include <driver/pci/msi.h>
/**
* @brief 生成msi消息
*
* @param msi_desc msi描述符
* @return struct msi_msg_t* msi消息指针在描述符内
*/
struct msi_msg_t *msi_arch_get_msg(struct msi_desc_t *msi_desc);

View File

@ -0,0 +1,69 @@
#include <common/stddef.h>
/**
* @brief 统计二进制数的前导0
*
* @param x 待统计的数
* @return int 结果
*/
static __always_inline int __clz(uint32_t x)
{
asm volatile("bsr %%eax, %%eax\n\t"
"xor $0x1f, %%eax\n\t"
: "=a"(x)
: "a"(x)
: "memory");
return x;
}
/**
* @brief 统计二进制数的前导0 (宽度为unsigned long)
*
* @param x 待统计的数
* @return int 结果
*/
static __always_inline int __clzl(unsigned long x)
{
int res = 0;
asm volatile("cltq\n\t"
"bsr %%rax, %%rax\n\t"
"xor $0x3f, %%rax\n\t"
"mov %%eax,%0\n\t"
: "=m"(res)
: "a"(x)
: "memory");
return res;
}
/**
* @brief 统计二进制数的前导0宽度为unsigned long long
*
* @param x 待统计的数
* @return int 结果
*/
static __always_inline int __clzll(unsigned long long x)
{
int res = 0;
asm volatile("cltq\n\t"
"bsr %%rax, %%rax\n\t"
"xor $0x3f, %%rax\n\t"
"mov %%eax,%0\n\t"
: "=m"(res)
: "a"(x)
: "memory");
return res;
}
static __always_inline int __ctz(uint32_t x)
{
asm volatile("tzcnt %%eax, %%eax":"=a"(x):"a"(x):"memory");
return x;
}
static __always_inline int __ctzl(unsigned long x)
{
asm volatile("tzcnt %%rax, %%rax":"=a"(x):"a"(x):"memory");
return x;
}
#define __ctzll __ctzl

View File

@ -0,0 +1,15 @@
{
"llvm-target": "x86_64-unknown-none",
"data-layout": "e-m:e-i64:64-f80:128-n8:16:32:64-S128",
"arch": "x86_64",
"target-endian": "little",
"target-pointer-width": "64",
"target-c-int-width": "32",
"os": "none",
"linker": "rust-lld",
"linker-flavor": "ld.lld",
"executables": true,
"features": "-mmx,-sse,+soft-float",
"disable-redzone": true,
"panic-strategy": "abort"
}

View File

@ -0,0 +1,49 @@
#include "x86_64_ipi.h"
#include <driver/interrupt/apic/apic.h>
void ipi_send_IPI(uint32_t dest_mode, uint32_t deliver_status, uint32_t level, uint32_t trigger,
uint32_t vector, uint32_t deliver_mode, uint32_t dest_shorthand, uint32_t destination)
{
struct INT_CMD_REG icr_entry;
icr_entry.dest_mode = dest_mode;
icr_entry.deliver_status = deliver_status;
icr_entry.res_1 = 0;
icr_entry.level = level;
icr_entry.trigger = trigger;
icr_entry.res_2 = 0;
icr_entry.res_3 = 0;
icr_entry.vector = vector;
icr_entry.deliver_mode = deliver_mode;
icr_entry.dest_shorthand = dest_shorthand;
// x2APIC下ICR寄存器地址为0x830
// xAPIC下则为0xfee00300(31-0) 0xfee00310 (63-32)
if (CURRENT_APIC_STATE == APIC_X2APIC_ENABLED) // x2APIC
{
icr_entry.destination.x2apic_destination = destination;
wrmsr(0x830, *(unsigned long *)&icr_entry); // 发送ipi
}
else // xAPIC
{
icr_entry.destination.apic_destination.dest_field = destination & 0xff;
icr_entry.destination.apic_destination.res_4 = 0;
// 先向高32bit写数据然后再向低32bit写数据不能调转
*(uint32_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + 0x310) = (uint32_t)(((*(ul *)&icr_entry) >> 32) & 0xffffffff);
*(uint32_t *)(APIC_LOCAL_APIC_VIRT_BASE_ADDR + 0x300) = (uint32_t)((*(ul *)&icr_entry) & 0xffffffff);
}
}
int ipi_regiserIPI(uint64_t irq_num, void *arg,
void (*handler)(uint64_t irq_num, uint64_t param, struct pt_regs *regs),
uint64_t param, hardware_intr_controller *controller, char *irq_name)
{
irq_desc_t *p = &SMP_IPI_desc[irq_num - 200];
p->controller = NULL; // 由于ipi不涉及到具体的硬件操作因此不需要controller
p->irq_name = irq_name;
p->parameter = param;
p->flags = 0;
p->handler = handler;
return 0;
}

View File

@ -0,0 +1,45 @@
/**
* @file ipi.h
* @author fslongjin(longjin@RinGoTek.cn)
* @brief 多核通信驱动
* @version 0.1
* @date 2022-04-07
*
* @copyright Copyright (c) 2022
*
*/
#pragma once
#include <common/kprint.h>
#include <driver/interrupt/apic/apic.h>
/**
* @brief 发送ipi消息
*
* @param dest_mode 目标模式
* @param deliver_status 投递模式
* @param level 信号驱动电平
* @param trigger 触发模式
* @param vector 中断向量
* @param deliver_mode 投递模式
* @param dest_shorthand 投递目标速记值
* @param destination 投递目标
*/
void ipi_send_IPI(uint32_t dest_mode, uint32_t deliver_status, uint32_t level, uint32_t trigger,
uint32_t vector, uint32_t deliver_mode, uint32_t dest_shorthand, uint32_t destination);
/**
* @brief ipi中断处理注册函数
*
* @param irq_num 中断向量号
* @param arg 参数
* @param handler 处理函数
* @param param 参数
* @param controller 当前为NULL
* @param irq_name ipi中断名
* @return int 成功0
*/
int ipi_regiserIPI(uint64_t irq_num, void *arg,
void (*handler)(uint64_t irq_num, uint64_t param, struct pt_regs *regs),
uint64_t param, hardware_intr_controller *controller, char *irq_name);