添加中断 (#370)

* 添加中断

* dhcp更改为全局socketset

* 解决异常中断的问题,使得能够使用中断来处理网卡数据

---------

Co-authored-by: longjin <longjin@RinGoTek.cn>
This commit is contained in:
YJwu2023 2023-09-21 23:23:57 +08:00 committed by GitHub
parent 6b4e7a2972
commit 0dd8ff4332
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 120 additions and 54 deletions

View File

@ -16,7 +16,6 @@ bitflags = "1.3.2"
virtio-drivers = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/virtio-drivers.git", rev = "f1d1cbb" } virtio-drivers = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/virtio-drivers.git", rev = "f1d1cbb" }
# 一个无锁MPSC队列 # 一个无锁MPSC队列
thingbuf = { version = "0.1.3", default-features = false, features = ["alloc"] } thingbuf = { version = "0.1.3", default-features = false, features = ["alloc"] }
# smoltcp 0.9.1
smoltcp = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/smoltcp.git", rev = "9027825", default-features = false, features = ["log", "alloc", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "socket-dhcpv4", "socket-dns", "proto-ipv4", "proto-ipv6"]} smoltcp = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/smoltcp.git", rev = "9027825", default-features = false, features = ["log", "alloc", "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "socket-dhcpv4", "socket-dns", "proto-ipv4", "proto-ipv6"]}
# num-traits 0.2.15 # num-traits 0.2.15
num-traits = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false } num-traits = { git = "https://git.mirrors.dragonos.org/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false }

View File

@ -3,7 +3,7 @@ use crate::driver::pci::pci_irq::TriggerMode;
/// @param processor 目标CPU ID号 /// @param processor 目标CPU ID号
/// @return MSI Message Address /// @return MSI Message Address
pub fn ia64_pci_get_arch_msi_message_address(processor: u16) -> u32 { pub fn ia64_pci_get_arch_msi_message_address(processor: u16) -> u32 {
0xfee00000 as u32 | ((processor as u32) << 12) 0xfee00000 | ((processor as u32) << 12)
} }
/// @brief 获得MSI Message Data /// @brief 获得MSI Message Data
/// @param vector 分配的中断向量号 /// @param vector 分配的中断向量号

View File

@ -14,7 +14,7 @@
#pragma GCC push_options #pragma GCC push_options
#pragma GCC optimize("O0") #pragma GCC optimize("O0")
// 导出定义在irq.c中的中段门表 // 导出定义在irq.c中的中段门表
extern void (*interrupt_table[24])(void); extern void (*interrupt_table[25])(void);
extern uint32_t rs_current_pcb_preempt_count(); extern uint32_t rs_current_pcb_preempt_count();
extern uint32_t rs_current_pcb_pid(); extern uint32_t rs_current_pcb_pid();
extern uint32_t rs_current_pcb_flags(); extern uint32_t rs_current_pcb_flags();
@ -363,7 +363,7 @@ int apic_init()
cli(); cli();
kinfo("Initializing APIC..."); kinfo("Initializing APIC...");
// 初始化中断门, 中断使用rsp0防止在软中断时发生嵌套然后处理器重新加载导致数据被抹掉 // 初始化中断门, 中断使用rsp0防止在软中断时发生嵌套然后处理器重新加载导致数据被抹掉
for (int i = 32; i <= 55; ++i) for (int i = 32; i <= 56; ++i)
set_intr_gate(i, 0, interrupt_table[i - 32]); set_intr_gate(i, 0, interrupt_table[i - 32]);
// 设置local apic中断门 // 设置local apic中断门
@ -413,7 +413,6 @@ int apic_init()
*/ */
void do_IRQ(struct pt_regs *rsp, ul number) void do_IRQ(struct pt_regs *rsp, ul number)
{ {
if (number < 0x80 && number >= 32) // 以0x80为界限低于0x80的是外部中断控制器高于0x80的是Local APIC if (number < 0x80 && number >= 32) // 以0x80为界限低于0x80的是外部中断控制器高于0x80的是Local APIC
{ {
// ==========外部中断控制器======== // ==========外部中断控制器========

View File

@ -8,19 +8,15 @@
// 现在pci设备的中断由自己进行控制这些不执行内容的函数是为了适配旧的中断处理机制 // 现在pci设备的中断由自己进行控制这些不执行内容的函数是为了适配旧的中断处理机制
void pci_irq_enable(ul irq_num) void pci_irq_enable(ul irq_num)
{ {
} }
void pci_irq_disable(ul irq_num) void pci_irq_disable(ul irq_num)
{ {
} }
ul pci_irq_install(ul, void*) ul pci_irq_install(ul, void*)
{ {
} }
void pci_irq_uninstall(ul irq_num) void pci_irq_uninstall(ul irq_num)
{ {
} }
/// @brief 与本操作系统的中断机制进行交互把中断处理函数等注册到中断结构体中被rust调用 /// @brief 与本操作系统的中断机制进行交互把中断处理函数等注册到中断结构体中被rust调用
/// @param irq_num 要进行注册的中断号 /// @param irq_num 要进行注册的中断号
@ -28,27 +24,27 @@ void pci_irq_uninstall(ul irq_num)
/// @param parameter 中断处理函数传入参数 /// @param parameter 中断处理函数传入参数
/// @param irq_name 中断名字 /// @param irq_name 中断名字
/// @param pci_irq_ack 对于中断的回复为NULL时会使用默认回应 /// @param pci_irq_ack 对于中断的回复为NULL时会使用默认回应
uint16_t c_irq_install(ul irq_num,void (*pci_irq_handler)(ul irq_num, ul parameter, struct pt_regs *regs),ul parameter,const char *irq_name,void (*pci_irq_ack)(ul irq_num)) uint16_t c_irq_install(ul irq_num, void (*pci_irq_handler)(ul irq_num, ul parameter, struct pt_regs *regs), ul parameter, const char *irq_name, void (*pci_irq_ack)(ul irq_num))
{ {
// 由于为I/O APIC分配的中断向量号是从32开始的因此要减去32才是对应的interrupt_desc的元素 // 由于为I/O APIC分配的中断向量号是从32开始的因此要减去32才是对应的interrupt_desc的元素
irq_desc_t *p = NULL; irq_desc_t *p = NULL;
hardware_intr_controller *pci_interrupt_controller = NULL;
if (irq_num >= 32 && irq_num < 0x80) if (irq_num >= 32 && irq_num < 0x80)
p = &interrupt_desc[irq_num - 32]; p = &interrupt_desc[irq_num - 32];
else if (irq_num >= 150 && irq_num < 200) else if (irq_num >= 150 && irq_num < 200)
p = &local_apic_interrupt_desc[irq_num - 150]; p = &local_apic_interrupt_desc[irq_num - 150];
else else
{ {
//kerror("irq install for pci irq: invalid irq num: %ld.", irq_num); // kerror("irq install for pci irq: invalid irq num: %ld.", irq_num);
return EINVAL; return EINVAL;
} }
if(p->irq_name!=NULL) if (p->irq_name != NULL)
{ {
return EAGAIN; return EAGAIN;
} }
pci_interrupt_controller = kzalloc(sizeof(hardware_intr_controller), 0);
hardware_intr_controller* pci_interrupt_controller = if (pci_interrupt_controller)
(hardware_intr_controller*)kmalloc(sizeof(hardware_intr_controller), 0); {
if (pci_interrupt_controller) {
pci_interrupt_controller->enable = pci_irq_enable; pci_interrupt_controller->enable = pci_irq_enable;
pci_interrupt_controller->disable = pci_irq_disable; pci_interrupt_controller->disable = pci_irq_disable;
pci_interrupt_controller->install = pci_irq_install; pci_interrupt_controller->install = pci_irq_install;
@ -56,8 +52,12 @@ uint16_t c_irq_install(ul irq_num,void (*pci_irq_handler)(ul irq_num, ul paramet
pci_interrupt_controller->ack = pci_irq_ack; pci_interrupt_controller->ack = pci_irq_ack;
p->controller = pci_interrupt_controller; p->controller = pci_interrupt_controller;
} }
else
{
return EAGAIN;
}
size_t namelen = strlen(irq_name) + 1; size_t namelen = strlen(irq_name) + 1;
p->irq_name = (char *)kmalloc(namelen, 0); p->irq_name = (char *)kzalloc(namelen, 0);
memset(p->irq_name, 0, namelen); memset(p->irq_name, 0, namelen);
strncpy(p->irq_name, irq_name, namelen); strncpy(p->irq_name, irq_name, namelen);
p->parameter = parameter; p->parameter = parameter;
@ -80,12 +80,12 @@ void c_irq_uninstall(ul irq_num)
{ {
kerror("irq install for pci irq: invalid irq num: %ld.", irq_num); kerror("irq install for pci irq: invalid irq num: %ld.", irq_num);
} }
if(p->irq_name != NULL) if (p->irq_name != NULL)
{ {
kfree(p->irq_name); kfree(p->irq_name);
p->irq_name = NULL; p->irq_name = NULL;
} }
if(p->controller != NULL) if (p->controller != NULL)
{ {
kfree(p->controller); kfree(p->controller);
p->controller = NULL; p->controller = NULL;

View File

@ -12,15 +12,16 @@ use crate::arch::{PciArch, TraitPciArch};
use crate::include::bindings::bindings::{ use crate::include::bindings::bindings::{
c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL, c_irq_install, c_irq_uninstall, pt_regs, ul, EAGAIN, EINVAL,
}; };
use crate::kdebug;
use crate::libs::volatile::{volread, volwrite, Volatile, VolatileReadable, VolatileWritable}; use crate::libs::volatile::{volread, volwrite, Volatile, VolatileReadable, VolatileWritable};
/// MSIX表的一项 /// MSIX表的一项
#[repr(C)] #[repr(C)]
struct MsixEntry { struct MsixEntry {
vector_control: Volatile<u32>,
msg_data: Volatile<u32>,
msg_upper_addr: Volatile<u32>,
msg_addr: Volatile<u32>, msg_addr: Volatile<u32>,
msg_upper_addr: Volatile<u32>,
msg_data: Volatile<u32>,
vector_control: Volatile<u32>,
} }
/// Pending表的一项 /// Pending表的一项
#[repr(C)] #[repr(C)]
@ -66,17 +67,17 @@ pub enum IrqType {
// PCI设备install中断时需要传递的参数 // PCI设备install中断时需要传递的参数
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct IrqMsg { pub struct IrqMsg {
irq_common_message: IrqCommonMsg, pub irq_common_message: IrqCommonMsg,
irq_specific_message: IrqSpecificMsg, pub irq_specific_message: IrqSpecificMsg,
} }
// PCI设备install中断时需要传递的共同参数 // PCI设备install中断时需要传递的共同参数
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct IrqCommonMsg { pub struct IrqCommonMsg {
irq_index: u16, //要install的中断号在PCI设备中的irq_vector的index pub irq_index: u16, //要install的中断号在PCI设备中的irq_vector的index
irq_name: CString, //中断名字 pub irq_name: CString, //中断名字
irq_parameter: u16, //中断额外参数,可传入中断处理函数 pub irq_parameter: u16, //中断额外参数,可传入中断处理函数
irq_hander: unsafe extern "C" fn(irq_num: ul, parameter: ul, regs: *mut pt_regs), // 中断处理函数 pub irq_hander: unsafe extern "C" fn(irq_num: ul, parameter: ul, regs: *mut pt_regs), // 中断处理函数
irq_ack: Option<unsafe extern "C" fn(irq_num: ul)>, // 中断的ack可为None,若为None则中断处理中会正常通知中断结束不为None则调用传入的函数进行回复 pub irq_ack: Option<unsafe extern "C" fn(irq_num: ul)>, // 中断的ack可为None,若为None则中断处理中会正常通知中断结束不为None则调用传入的函数进行回复
} }
// PCI设备install中断时需要传递的特有参数Msi代表MSI与MSIX // PCI设备install中断时需要传递的特有参数Msi代表MSI与MSIX
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -88,7 +89,7 @@ pub enum IrqSpecificMsg {
}, },
} }
impl IrqSpecificMsg { impl IrqSpecificMsg {
fn msi_default() -> Self { pub fn msi_default() -> Self {
IrqSpecificMsg::Msi { IrqSpecificMsg::Msi {
processor: 0, processor: 0,
trigger_mode: TriggerMode::EdgeTrigger, trigger_mode: TriggerMode::EdgeTrigger,
@ -122,16 +123,16 @@ pub trait PciInterrupt: PciDeviceStructure {
if flag.contains(IRQ::PCI_IRQ_MSIX) { if flag.contains(IRQ::PCI_IRQ_MSIX) {
if let Some(cap_offset) = self.msix_capability_offset() { if let Some(cap_offset) = self.msix_capability_offset() {
let data = let data =
PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 4); PciArch::read_config(&self.common_header().bus_device_function, cap_offset);
let irq_max_num = ((data >> 16) & 0x07ff) as u16; let irq_max_num = ((data >> 16) & 0x7ff) as u16 + 1;
let data = let data =
PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 4); PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 4);
let msix_table_bar = (data & 0x01) as u8; let msix_table_bar = (data & 0x07) as u8;
let msix_table_offset = data & 0xfffe; let msix_table_offset = data & (!0x07);
let data = let data =
PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 8); PciArch::read_config(&self.common_header().bus_device_function, cap_offset + 8);
let pending_table_bar = (data & 0x01) as u8; let pending_table_bar = (data & 0x07) as u8;
let pending_table_offset = data & 0xfffe; let pending_table_offset = data & (!0x07);
*self.irq_type_mut()? = IrqType::Msix { *self.irq_type_mut()? = IrqType::Msix {
msix_table_bar, msix_table_bar,
msix_table_offset, msix_table_offset,
@ -503,12 +504,13 @@ pub trait PciInterrupt: PciDeviceStructure {
.bar() .bar()
.ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))?; .ok_or(PciError::PciIrqError(PciIrqError::PciBarNotInited))?;
let msix_bar = pcistandardbar.get_bar(msix_table_bar)?; let msix_bar = pcistandardbar.get_bar(msix_table_bar)?;
let vaddr = msix_bar let vaddr: crate::mm::VirtAddr = msix_bar
.virtual_address() .virtual_address()
.ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed))? .ok_or(PciError::PciIrqError(PciIrqError::BarGetVaddrFailed))?
+ msix_table_offset as usize + msix_table_offset as usize
+ msg.irq_common_message.irq_index as usize * size_of::<MsixEntry>(); + msg.irq_common_message.irq_index as usize * size_of::<MsixEntry>();
let msix_entry = NonNull::new(vaddr.data() as *mut MsixEntry).unwrap(); let msix_entry = NonNull::new(vaddr.data() as *mut MsixEntry).unwrap();
kdebug!("msg_data: {:?}, msix_addr: {:?}", msg_data, msg_address);
unsafe { unsafe {
volwrite!(msix_entry, vector_control, 0); volwrite!(msix_entry, vector_control, 0);
volwrite!(msix_entry, msg_data, msg_data); volwrite!(msix_entry, msg_data, msg_data);

View File

@ -5,10 +5,15 @@ use crate::driver::pci::pci::{
PciStandardDeviceBar, PCI_CAP_ID_VNDR, PciStandardDeviceBar, PCI_CAP_ID_VNDR,
}; };
use crate::driver::pci::pci_irq::{IrqCommonMsg, IrqMsg, IrqSpecificMsg, PciInterrupt, IRQ};
use crate::include::bindings::bindings::pt_regs;
use crate::kdebug;
use crate::libs::volatile::{ use crate::libs::volatile::{
volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly, volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
}; };
use crate::mm::VirtAddr; use crate::mm::VirtAddr;
use crate::net::net_core::poll_ifaces_try_lock_onetime;
use alloc::ffi::CString;
use core::{ use core::{
fmt::{self, Display, Formatter}, fmt::{self, Display, Formatter},
mem::{align_of, size_of}, mem::{align_of, size_of},
@ -53,6 +58,12 @@ const VIRTIO_PCI_CAP_ISR_CFG: u8 = 3;
/// Device specific configuration. /// Device specific configuration.
const VIRTIO_PCI_CAP_DEVICE_CFG: u8 = 4; const VIRTIO_PCI_CAP_DEVICE_CFG: u8 = 4;
/// Virtio设备接收中断的设备号
const VIRTIO_RECV_VECTOR: u16 = 56;
/// Virtio设备接收中断的设备号的表项号
const VIRTIO_RECV_VECTOR_INDEX: u16 = 0;
// 接收的queue
const QUEUE_RECEIVE: u16 = 0;
///@brief device id 转换为设备类型 ///@brief device id 转换为设备类型
///@param pci_device_iddevice_id ///@param pci_device_iddevice_id
///@return DeviceType 对应的设备类型 ///@return DeviceType 对应的设备类型
@ -89,6 +100,11 @@ pub struct PciTransport {
config_space: Option<NonNull<[u32]>>, config_space: Option<NonNull<[u32]>>,
} }
unsafe extern "C" fn virtio_irq_hander(_irq_num: u64, _irq_paramer: u64, _regs: *mut pt_regs) {
// kdebug!("12345");
poll_ifaces_try_lock_onetime().ok();
}
impl PciTransport { impl PciTransport {
/// Construct a new PCI VirtIO device driver for the given device function on the given PCI /// Construct a new PCI VirtIO device driver for the given device function on the given PCI
/// root controller. /// root controller.
@ -111,6 +127,30 @@ impl PciTransport {
let mut device_cfg = None; let mut device_cfg = None;
device.bar_ioremap().unwrap()?; device.bar_ioremap().unwrap()?;
device.enable_master(); device.enable_master();
let standard_device = device.as_standard_device_mut().unwrap();
// 目前缺少对PCI设备中断号的统一管理所以这里需要指定一个中断号。不能与其他中断重复
let irq_vector = standard_device.irq_vector_mut().unwrap();
irq_vector.push(VIRTIO_RECV_VECTOR);
standard_device
.irq_init(IRQ::PCI_IRQ_MSIX)
.expect("IRQ init failed");
// 中断相关信息
let msg = IrqMsg {
irq_common_message: IrqCommonMsg {
irq_index: 0,
irq_name: CString::new(
"Virtio_Recv_
IRQ",
)
.expect("CString::new failed"),
irq_parameter: 0,
irq_hander: virtio_irq_hander,
irq_ack: None,
},
irq_specific_message: IrqSpecificMsg::msi_default(),
};
standard_device.irq_install(msg)?;
standard_device.irq_enable(true)?;
//device_capability为迭代器遍历其相当于遍历所有的cap空间 //device_capability为迭代器遍历其相当于遍历所有的cap空间
for capability in device.capabilities().unwrap() { for capability in device.capabilities().unwrap() {
if capability.id != PCI_CAP_ID_VNDR { if capability.id != PCI_CAP_ID_VNDR {
@ -268,16 +308,19 @@ impl Transport for PciTransport {
) { ) {
// Safe because the common config pointer is valid and we checked in get_bar_region that it // Safe because the common config pointer is valid and we checked in get_bar_region that it
// was aligned. // was aligned.
// kdebug!("queue_select={}",queue);
// kdebug!("queue_size={}",size as u16);
// kdebug!("queue_desc={:#x}",descriptors as u64);
// kdebug!("driver_area={:#x}",driver_area);
unsafe { unsafe {
volwrite!(self.common_cfg, queue_select, queue); volwrite!(self.common_cfg, queue_select, queue);
volwrite!(self.common_cfg, queue_size, size as u16); volwrite!(self.common_cfg, queue_size, size as u16);
volwrite!(self.common_cfg, queue_desc, descriptors as u64); volwrite!(self.common_cfg, queue_desc, descriptors as u64);
volwrite!(self.common_cfg, queue_driver, driver_area as u64); volwrite!(self.common_cfg, queue_driver, driver_area as u64);
volwrite!(self.common_cfg, queue_device, device_area as u64); volwrite!(self.common_cfg, queue_device, device_area as u64);
if queue == QUEUE_RECEIVE {
volwrite!(self.common_cfg, queue_msix_vector, VIRTIO_RECV_VECTOR_INDEX);
let vector = volread!(self.common_cfg, queue_msix_vector);
if vector != VIRTIO_RECV_VECTOR_INDEX {
panic!("Vector set failed");
}
}
volwrite!(self.common_cfg, queue_enable, 1); volwrite!(self.common_cfg, queue_enable, 1);
} }
} }

View File

@ -86,9 +86,10 @@ Build_IRQ(0x34);
Build_IRQ(0x35); Build_IRQ(0x35);
Build_IRQ(0x36); Build_IRQ(0x36);
Build_IRQ(0x37); Build_IRQ(0x37);
Build_IRQ(0x38);
// 初始化中断数组 // 初始化中断数组
void (*interrupt_table[24])(void) = { void (*interrupt_table[25])(void) = {
IRQ0x20interrupt, IRQ0x20interrupt,
IRQ0x21interrupt, IRQ0x21interrupt,
IRQ0x22interrupt, IRQ0x22interrupt,
@ -113,6 +114,7 @@ void (*interrupt_table[24])(void) = {
IRQ0x35interrupt, IRQ0x35interrupt,
IRQ0x36interrupt, IRQ0x36interrupt,
IRQ0x37interrupt, IRQ0x37interrupt,
IRQ0x38interrupt,
}; };
/** /**

View File

@ -16,11 +16,11 @@
#pragma GCC push_options #pragma GCC push_options
#pragma GCC optimize ("O0") #pragma GCC optimize ("O0")
#define IRQ_NUM 24 #define IRQ_NUM 25
#define SMP_IRQ_NUM 10 #define SMP_IRQ_NUM 10
#define LOCAL_APIC_IRQ_NUM 50 #define LOCAL_APIC_IRQ_NUM 50
extern void (*interrupt_table[24])(void); extern void (*interrupt_table[25])(void);
extern void do_IRQ(struct pt_regs *regs, ul number); extern void do_IRQ(struct pt_regs *regs, ul number);
@ -82,6 +82,7 @@ extern void (*local_apic_interrupt_table[LOCAL_APIC_IRQ_NUM])(void);
53 PIRQF 53 PIRQF
54 PIRQG 54 PIRQG
55 PIRQH 55 PIRQH
56 VIRTIO_RECV
0x80 system call 0x80 system call

View File

@ -31,11 +31,12 @@ impl TimerFunction for NetWorkPollFunc {
pub fn net_init() -> Result<(), SystemError> { pub fn net_init() -> Result<(), SystemError> {
dhcp_query()?; dhcp_query()?;
// Init poll timer function // Init poll timer function
let next_time = next_n_ms_timer_jiffies(5); // let next_time = next_n_ms_timer_jiffies(5);
let timer = Timer::new(Box::new(NetWorkPollFunc), next_time); // let timer = Timer::new(Box::new(NetWorkPollFunc), next_time);
timer.activate(); // timer.activate();
return Ok(()); return Ok(());
} }
fn dhcp_query() -> Result<(), SystemError> { fn dhcp_query() -> Result<(), SystemError> {
let binding = NET_DRIVERS.write(); let binding = NET_DRIVERS.write();
@ -52,15 +53,14 @@ fn dhcp_query() -> Result<(), SystemError> {
// IMPORTANT: This should be removed in production. // IMPORTANT: This should be removed in production.
dhcp_socket.set_max_lease_duration(Some(smoltcp::time::Duration::from_secs(10))); dhcp_socket.set_max_lease_duration(Some(smoltcp::time::Duration::from_secs(10)));
let mut sockets = smoltcp::iface::SocketSet::new(vec![]); let dhcp_handle = SOCKET_SET.lock().add(dhcp_socket);
let dhcp_handle = sockets.add(dhcp_socket);
const DHCP_TRY_ROUND: u8 = 10; const DHCP_TRY_ROUND: u8 = 10;
for i in 0..DHCP_TRY_ROUND { for i in 0..DHCP_TRY_ROUND {
kdebug!("DHCP try round: {}", i); kdebug!("DHCP try round: {}", i);
let _flag = net_face.poll(&mut sockets); net_face.poll(&mut SOCKET_SET.lock()).ok();
let event = sockets.get_mut::<dhcpv4::Socket>(dhcp_handle).poll(); let mut binding = SOCKET_SET.lock();
// kdebug!("event = {event:?} !!!"); let event = binding.get_mut::<dhcpv4::Socket>(dhcp_handle).poll();
match event { match event {
None => {} None => {}
@ -161,3 +161,23 @@ pub fn poll_ifaces_try_lock(times: u16) -> Result<(), SystemError> {
// 尝试次数用完,返回错误 // 尝试次数用完,返回错误
return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
} }
/// 对ifaces进行轮询。
///
/// @return 轮询成功返回Ok(())
/// @return 加锁超时返回SystemError::EAGAIN_OR_EWOULDBLOCK
/// @return 没有网卡返回SystemError::ENODEV
pub fn poll_ifaces_try_lock_onetime() -> Result<(), SystemError> {
let guard: RwLockReadGuard<BTreeMap<usize, Arc<dyn NetDriver>>> = NET_DRIVERS.read();
if guard.len() == 0 {
kwarn!("poll_ifaces: No net driver found!");
// 没有网卡,返回错误
return Err(SystemError::ENODEV);
}
let mut sockets = SOCKET_SET.try_lock()?;
for (_, iface) in guard.iter() {
iface.poll(&mut sockets).ok();
}
SOCKET_WAITQUEUE.wakeup_all(None);
return Ok(());
}

View File

@ -62,8 +62,8 @@ QEMU_DRIVE="id=disk,file=${QEMU_DISK_IMAGE},if=none"
# ps: 下面这条使用tap的方式无法dhcp获取到ip暂时不知道为什么 # ps: 下面这条使用tap的方式无法dhcp获取到ip暂时不知道为什么
# QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,netdev=nic0 -netdev tap,id=nic0,model=virtio-net-pci,script=qemu/ifup-nat,downscript=qemu/ifdown-nat -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel} -machine q35 " # QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -net nic,netdev=nic0 -netdev tap,id=nic0,model=virtio-net-pci,script=qemu/ifup-nat,downscript=qemu/ifdown-nat -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel} -machine q35 "
QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -nic user,model=virtio-net-pci,hostfwd=tcp::12580-:12580 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel} -machine q35 " #QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -nic user,model=virtio-net-pci,hostfwd=tcp::12580-:12580 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel} -machine q35 "
QEMU_DEVICES="-device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -netdev user,id=hostnet0,hostfwd=tcp::12580-:12580 -device virtio-net-pci,vectors=5,netdev=hostnet0,id=net0 -usb -device qemu-xhci,id=xhci,p2=8,p3=4 -machine accel=${qemu_accel} -machine q35 "
QEMU_ARGUMENT="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d -monitor ${QEMU_MONITOR} -d ${qemu_trace_std} " QEMU_ARGUMENT="-d ${QEMU_DISK_IMAGE} -m ${QEMU_MEMORY} -smp ${QEMU_SMP} -boot order=d -monitor ${QEMU_MONITOR} -d ${qemu_trace_std} "
QEMU_ARGUMENT+="-s -S -cpu ${QEMU_CPU_FEATURES} -rtc ${QEMU_RTC_CLOCK} -serial ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES}" QEMU_ARGUMENT+="-s -S -cpu ${QEMU_CPU_FEATURES} -rtc ${QEMU_RTC_CLOCK} -serial ${QEMU_SERIAL} -drive ${QEMU_DRIVE} ${QEMU_DEVICES}"