bugfix: 解决了xhci驱动程序无法在真机上获取设备描述符的bug

This commit is contained in:
fslongjin 2022-09-04 20:57:00 +08:00
parent 2551e0a8c9
commit 94c960ae89
7 changed files with 106 additions and 102 deletions

View File

@ -17,7 +17,7 @@ static int usb_pdevs_count = 0;
* @brief usb驱动程序 * @brief usb驱动程序
* *
*/ */
void usb_init() int usb_init()
{ {
kinfo("Initializing usb driver..."); kinfo("Initializing usb driver...");
spin_init(&xhci_controller_init_lock); spin_init(&xhci_controller_init_lock);
@ -30,7 +30,7 @@ void usb_init()
kwarn("There is no usb hardware in this computer!"); kwarn("There is no usb hardware in this computer!");
return; return;
} }
kdebug("usb_pdevs_count=%d",usb_pdevs_count); kdebug("usb_pdevs_count=%d", usb_pdevs_count);
// 初始化每个usb控制器 // 初始化每个usb控制器
for (volatile int i = 0; i < usb_pdevs_count; ++i) for (volatile int i = 0; i < usb_pdevs_count; ++i)
{ {
@ -59,4 +59,5 @@ void usb_init()
} }
} }
kinfo("Successfully initialized all usb host controllers!"); kinfo("Successfully initialized all usb host controllers!");
return 0;
} }

View File

@ -133,4 +133,4 @@ enum
* @brief usb驱动程序 * @brief usb驱动程序
* *
*/ */
void usb_init(); int usb_init();

View File

@ -47,9 +47,6 @@ static int xhci_data_stage(struct xhci_ep_ring_info_t *ep, uint64_t buf_vaddr, u
static int xhci_status_stage(const int id, uint8_t direction, uint64_t status_buf_vaddr); static int xhci_status_stage(const int id, uint8_t direction, uint64_t status_buf_vaddr);
static int xhci_wait_for_interrupt(const int id, uint64_t status_vaddr); static int xhci_wait_for_interrupt(const int id, uint64_t status_vaddr);
static struct xhci_ep_context_t ep_ctx = {0};
struct xhci_slot_context_t slot_ctx = {0};
hardware_intr_controller xhci_hc_intr_controller = hardware_intr_controller xhci_hc_intr_controller =
{ {
.enable = xhci_hc_irq_enable, .enable = xhci_hc_irq_enable,
@ -732,7 +729,8 @@ void xhci_hc_irq_handler(uint64_t irq_num, uint64_t cid, struct pt_regs *regs)
struct xhci_TRB_cmd_complete_t *event_trb_ptr = (struct xhci_TRB_cmd_complete_t *)&event_trb; struct xhci_TRB_cmd_complete_t *event_trb_ptr = (struct xhci_TRB_cmd_complete_t *)&event_trb;
if ((event_trb.command & (1 << 2)) == 0) // 当前event trb不是由于short packet产生的 if ((event_trb.command & (1 << 2)) == 0) // 当前event trb不是由于short packet产生的
{ {
// kdebug("event_trb_ptr->code=%d", event_trb_ptr->code);
// kdebug("event_trb_ptr->TRB_type=%d", event_trb_ptr->TRB_type);
switch (event_trb_ptr->code) // 判断它的完成码 switch (event_trb_ptr->code) // 判断它的完成码
{ {
case TRB_COMP_TRB_SUCCESS: // trb执行成功则将结果返回到对应的command ring的trb里面 case TRB_COMP_TRB_SUCCESS: // trb执行成功则将结果返回到对应的command ring的trb里面
@ -813,9 +811,7 @@ static int xhci_reset_port(const int id, const int port)
int retval = 0; int retval = 0;
// 相对于op寄存器基地址的偏移量 // 相对于op寄存器基地址的偏移量
uint64_t port_status_offset = XHCI_OPS_PRS + port * 16; uint64_t port_status_offset = XHCI_OPS_PRS + port * 16;
// kdebug("to reset %d, portsc=%#010lx", port, (xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC)));
// kdebug("to reset %d, usbcmd=%#010lx", port, xhci_read_op_reg32(id, XHCI_OPS_USBCMD));
// kdebug("to reset %d, usbsts=%#010lx", port, xhci_read_op_reg32(id, XHCI_OPS_USBSTS));
io_mfence(); io_mfence();
// 检查端口电源状态 // 检查端口电源状态
if ((xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC) & (1 << 9)) == 0) if ((xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC) & (1 << 9)) == 0)
@ -847,20 +843,22 @@ static int xhci_reset_port(const int id, const int port)
retval = -ETIMEDOUT; retval = -ETIMEDOUT;
// kdebug("to wait reset timeout;"); // kdebug("to wait reset timeout;");
// 等待portsc的port reset change位被置位说明reset完成 // 等待portsc的port reset change位被置位说明reset完成
int timeout = 200; int timeout = 100;
while (timeout) while (timeout)
{ {
io_mfence(); io_mfence();
uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC); uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC);
// kdebug("val=%#010lx", val);
io_mfence(); io_mfence();
if (val & (1 << 21))
break;
// QEMU对usb的模拟有bug因此需要检测这里
#ifdef __QEMU_EMULATION__
if (XHCI_PORT_IS_USB3(id, port) && (val & (1 << 31)) == 0) if (XHCI_PORT_IS_USB3(id, port) && (val & (1 << 31)) == 0)
break; break;
else if (XHCI_PORT_IS_USB2(id, port) && (val & (1 << 4)) == 0) else if (XHCI_PORT_IS_USB2(id, port) && (val & (1 << 4)) == 0)
break; break;
else if (val & (1 << 21)) #endif
break;
--timeout; --timeout;
usleep(500); usleep(500);
} }
@ -870,10 +868,11 @@ static int xhci_reset_port(const int id, const int port)
{ {
// 等待恢复 // 等待恢复
usleep(USB_TIME_RST_REC * 100); usleep(USB_TIME_RST_REC * 100);
// kdebug("to check if reset ok");
uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC); uint32_t val = xhci_read_op_reg32(id, port_status_offset + XHCI_PORT_PORTSC);
io_mfence(); io_mfence();
// kdebug("to check if reset ok, val=%#010lx", val);
// 如果reset之后enable bit仍然是1那么说明reset成功 // 如果reset之后enable bit仍然是1那么说明reset成功
if (val & (1 << 1)) if (val & (1 << 1))
{ {
@ -928,7 +927,7 @@ static uint64_t xhci_initialize_slot(const int id, const int slot_id, const int
// kdebug("slot id=%d, device_context_vaddr=%#018lx, port=%d", slot_id, device_context_vaddr, port); // kdebug("slot id=%d, device_context_vaddr=%#018lx, port=%d", slot_id, device_context_vaddr, port);
// 写到数组中 // 写到数组中
__write8b(xhci_hc[id].dcbaap_vaddr + (slot_id * sizeof(uint64_t)), virt_2_phys(device_context_vaddr)); __write8b(xhci_hc[id].dcbaap_vaddr + (slot_id * sizeof(uint64_t)), virt_2_phys(device_context_vaddr));
struct xhci_slot_context_t slot_ctx = {0};
slot_ctx.entries = 1; slot_ctx.entries = 1;
slot_ctx.speed = speed; slot_ctx.speed = speed;
slot_ctx.route_string = 0; slot_ctx.route_string = 0;
@ -964,6 +963,7 @@ static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const in
// 由于目前只实现获取设备的描述符因此暂时只支持control ep // 由于目前只实现获取设备的描述符因此暂时只支持control ep
if (type != USB_EP_CONTROL) if (type != USB_EP_CONTROL)
return; return;
struct xhci_ep_context_t ep_ctx = {0};
memset(&ep_ctx, 0, sizeof(struct xhci_ep_context_t)); memset(&ep_ctx, 0, sizeof(struct xhci_ep_context_t));
xhci_hc[id].control_ep_info.ep_ring_vbase = xhci_create_ring(XHCI_TRBS_PER_RING); xhci_hc[id].control_ep_info.ep_ring_vbase = xhci_create_ring(XHCI_TRBS_PER_RING);
@ -1004,6 +1004,8 @@ static void xhci_initialize_ep(const int id, const uint64_t slot_vaddr, const in
static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int slot_id, const bool block) static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int slot_id, const bool block)
{ {
int retval = 0; int retval = 0;
struct xhci_slot_context_t slot;
struct xhci_ep_context_t ep;
// 创建输入上下文缓冲区 // 创建输入上下文缓冲区
uint64_t input_ctx_buffer = (uint64_t)kzalloc(xhci_hc[id].context_size * 32, 0); uint64_t input_ctx_buffer = (uint64_t)kzalloc(xhci_hc[id].context_size * 32, 0);
@ -1011,9 +1013,16 @@ static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int s
__write4b(input_ctx_buffer + 4, 0x3); __write4b(input_ctx_buffer + 4, 0x3);
// 拷贝slot上下文和control ep上下文到输入上下文中 // 拷贝slot上下文和control ep上下文到输入上下文中
__write_slot(input_ctx_buffer + xhci_hc[id].context_size, (struct xhci_slot_context_t *)slot_vaddr);
__write_ep(id, input_ctx_buffer, 2, (struct xhci_ep_context_t *)(slot_vaddr + XHCI_EP_CONTROL * xhci_hc[id].context_size)); // __write_ep(id, input_ctx_buffer, 2, &ep_ctx);
__read_from_slot(&slot, slot_vaddr);
__read_from_ep(id, slot_vaddr, 1, &ep);
ep.err_cnt = 3;
kdebug("slot.slot_state=%d, speed=%d, root hub port num=%d", slot.slot_state, slot.speed, slot.rh_port_num);
kdebug("ep.type=%d, max_packet=%d, dequeue_ptr=%#018lx", ep.ep_type, ep.max_packet_size, ep.tr_dequeue_ptr);
__write_slot(input_ctx_buffer + xhci_hc[id].context_size, &slot);
__write_ep(id, input_ctx_buffer, 2, &ep);
struct xhci_TRB_normal_t trb = {0}; struct xhci_TRB_normal_t trb = {0};
trb.buf_paddr = virt_2_phys(input_ctx_buffer); trb.buf_paddr = virt_2_phys(input_ctx_buffer);
@ -1027,25 +1036,15 @@ static int xhci_set_address(const int id, const uint64_t slot_vaddr, const int s
if (unlikely(retval != 0)) if (unlikely(retval != 0))
{ {
kerror("slotid:%d, address device failed", slot_id); kerror("slotid:%d, address device failed", slot_id);
goto failed; goto failed;
} }
struct xhci_TRB_cmd_complete_t *trb_done = (struct xhci_TRB_cmd_complete_t *)&trb; struct xhci_TRB_cmd_complete_t *trb_done = (struct xhci_TRB_cmd_complete_t *)&trb;
// kdebug("address slot: comp code=%d", trb_done->code);
if (trb_done->code == TRB_COMP_TRB_SUCCESS) // 成功执行 if (trb_done->code == TRB_COMP_TRB_SUCCESS) // 成功执行
{ {
// 如果要从控制器获取刚刚设置的设备地址的话可以在这里读取slot context // 如果要从控制器获取刚刚设置的设备地址的话可以在这里读取slot context
// ksuccess("slot %d successfully addressed.", slot_id); ksuccess("slot %d successfully addressed.", slot_id);
struct xhci_slot_context_t slot;
struct xhci_ep_context_t ep;
__read_from_slot(&slot, slot_vaddr);
slot_ctx.slot_state = slot.slot_state;
slot_ctx.device_address = slot.device_address;
__read_from_ep(id, slot_vaddr, 1, &ep);
// kdebug("ep.ep_state=%d, slot_state=%d", ep.ep_state, slot.slot_state);
ep_ctx.ep_state = ep.ep_state;
ep_ctx.max_packet_size = ep.max_packet_size;
retval = 0; retval = 0;
} }
else else
@ -1323,12 +1322,13 @@ static int xhci_get_descriptor(const int id, const int port_id)
*/ */
struct xhci_TRB_normal_t trb = {0}; struct xhci_TRB_normal_t trb = {0};
trb.TRB_type = TRB_TYPE_ENABLE_SLOT; trb.TRB_type = TRB_TYPE_ENABLE_SLOT;
kdebug("to enable slot"); // kdebug("to enable slot");
if (xhci_send_command(id, (struct xhci_TRB_t *)&trb, true) != 0) if (xhci_send_command(id, (struct xhci_TRB_t *)&trb, true) != 0)
{ {
kerror("portid:%d: send enable slot failed", port_id); kerror("portid:%d: send enable slot failed", port_id);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
// kdebug("send enable slot ok");
uint32_t slot_id = ((struct xhci_TRB_cmd_complete_t *)&trb)->slot_id; uint32_t slot_id = ((struct xhci_TRB_cmd_complete_t *)&trb)->slot_id;
int16_t max_packet; int16_t max_packet;
@ -1350,48 +1350,27 @@ static int xhci_get_descriptor(const int id, const int port_id)
} }
} }
// kdebug("speed=%d", speed);
kdebug("speed=%d", speed);
// 初始化接口的上下文 // 初始化接口的上下文
uint64_t slot_vaddr = xhci_initialize_slot(id, slot_id, port_id, speed, max_packet); uint64_t slot_vaddr = xhci_initialize_slot(id, slot_id, port_id, speed, max_packet);
kdebug("set addr");
// 发送 address_device命令 // kdebug("set addr again");
retval = xhci_set_address(id, slot_vaddr, slot_id, true); // 再次发送 set_address命令
// kdebug("to set addr again");
retval = xhci_set_address(id, slot_vaddr, slot_id, false);
if (retval != 0) if (retval != 0)
return retval; return retval;
kdebug("crtl in");
// 发送用于 “get_descriptor” 的数据包。 // kdebug("ctrl in again");
count = xhci_control_in(id, &dev_desc, 8, slot_id, max_packet);
count = xhci_control_in(id, &dev_desc, 18, slot_id, max_packet);
if (unlikely(count == 0)) if (unlikely(count == 0))
return -EAGAIN; return -EAGAIN;
/* /*
TODO: if the dev_desc.max_packet was different than what we have as max_packet, TODO: if the dev_desc.max_packet was different than what we have as max_packet,
you would need to change it here and in the slot context by doing a you would need to change it here and in the slot context by doing a
evaluate_slot_context call. evaluate_slot_context call.
*/ */
kdebug("reset port");
// 重置当前端口
kdebug("to reset");
xhci_reset_port(id, port_id);
kdebug("set addr again");
// 再次发送 set_address命令
kdebug("to set addr again");
retval = xhci_set_address(id, slot_vaddr, slot_id, false);
if (retval != 0)
return retval;
kdebug("ctrl in again");
count = xhci_control_in(id, &dev_desc, 18, slot_id, max_packet);
if (unlikely(count == 0))
return -EAGAIN;
// print the descriptor // print the descriptor
printk(" Found USB Device:\n" printk(" Found USB Device:\n"
" port: %i\n" " port: %i\n"
@ -1430,18 +1409,22 @@ static int xhci_hc_start_ports(int id)
// 注意这两个循环应该不能合并到一起因为可能存在usb2端口offset在前usb3端口在后的情况那样的话就会出错 // 注意这两个循环应该不能合并到一起因为可能存在usb2端口offset在前usb3端口在后的情况那样的话就会出错
// 循环启动所有的usb3端口 // 循环启动所有的usb3端口
// for (int i = 0; i < xhci_hc[id].port_num; ++i) for (int i = 0; i < xhci_hc[id].port_num; ++i)
for (int i = 0; i < 1; ++i)
{ {
if (XHCI_PORT_IS_USB3(id, i) && XHCI_PORT_IS_ACTIVE(id, i)) if (XHCI_PORT_IS_USB3(id, i) && XHCI_PORT_IS_ACTIVE(id, i))
{ {
io_mfence(); io_mfence();
// kdebug("to reset port %d, rflags=%#018lx", id, get_rflags());
int rst_ret = xhci_reset_port(id, i);
// kdebug("reset done!, val=%d", rst_ret);
// reset该端口 // reset该端口
if (likely(xhci_reset_port(id, i) == 0)) // 如果端口reset成功就获取它的描述符 if (likely(rst_ret == 0)) // 如果端口reset成功就获取它的描述符
// 否则reset函数会把它给设置为未激活并且标志配对的usb2端口是激活的 // 否则reset函数会把它给设置为未激活并且标志配对的usb2端口是激活的
{ {
// kdebug("reset port %d ok", id);
if (xhci_get_descriptor(id, i) == 0) if (xhci_get_descriptor(id, i) == 0)
++cnt; ++cnt;
kdebug("usb3 port %d get desc ok", i);
} }
} }
} }
@ -1454,17 +1437,15 @@ static int xhci_hc_start_ports(int id)
{ {
// kdebug("initializing usb2: %d", i); // kdebug("initializing usb2: %d", i);
// reset该端口 // reset该端口
kdebug("to reset port %d, rflags=%#018lx", id, get_rflags()); // kdebug("to reset port %d, rflags=%#018lx", i, get_rflags());
if (likely(xhci_reset_port(id, i) == 0)) // 如果端口reset成功就获取它的描述符 if (likely(xhci_reset_port(id, i) == 0)) // 如果端口reset成功就获取它的描述符
// 否则reset函数会把它给设置为未激活并且标志配对的usb2端口是激活的 // 否则reset函数会把它给设置为未激活并且标志配对的usb2端口是激活的
{ {
kdebug("reset port %d ok", id); // kdebug("reset port %d ok", id);
if (xhci_get_descriptor(id, i) == 0) if (xhci_get_descriptor(id, i) == 0)
++cnt; ++cnt;
else kdebug("USB2 port %d get desc ok", i);
break;
kdebug("port %d get desc ok", id);
} }
} }
} }
@ -1711,6 +1692,23 @@ void xhci_init(struct pci_device_structure_general_device_t *dev_hdr)
// 写入dcbaap // 写入dcbaap
xhci_write_op_reg64(cid, XHCI_OPS_DCBAAP, virt_2_phys(xhci_hc[cid].dcbaap_vaddr)); xhci_write_op_reg64(cid, XHCI_OPS_DCBAAP, virt_2_phys(xhci_hc[cid].dcbaap_vaddr));
io_mfence(); io_mfence();
// 创建scratchpad buffer array
uint32_t max_scratchpad_buf = (((uint32_t)hcs2.max_scratchpad_buf_HI5) << 5) | hcs2.max_scratchpad_buf_LO5;
kdebug("max scratchpad buffer=%d", max_scratchpad_buf);
if (max_scratchpad_buf > 0)
{
xhci_hc[cid].scratchpad_buf_array_vaddr = (uint64_t)kzalloc(sizeof(uint64_t) * max_scratchpad_buf, 0);
__write8b(xhci_hc[cid].dcbaap_vaddr, virt_2_phys(xhci_hc[cid].scratchpad_buf_array_vaddr));
// 创建scratchpad buffers
for (int i = 0; i < max_scratchpad_buf; ++i)
{
uint64_t buf_vaddr = kzalloc(xhci_hc[cid].page_size, 0);
__write8b(xhci_hc[cid].scratchpad_buf_array_vaddr, virt_2_phys(buf_vaddr));
}
}
// 创建command ring // 创建command ring
xhci_hc[cid].cmd_ring_vaddr = xhci_create_ring(XHCI_CMND_RING_TRBS); xhci_hc[cid].cmd_ring_vaddr = xhci_create_ring(XHCI_CMND_RING_TRBS);
xhci_hc[cid].cmd_trb_vaddr = xhci_hc[cid].cmd_ring_vaddr; xhci_hc[cid].cmd_trb_vaddr = xhci_hc[cid].cmd_ring_vaddr;

View File

@ -518,22 +518,26 @@ struct xhci_host_controller_t
uint64_t vbase_op; // Operational registers 起始虚拟地址 uint64_t vbase_op; // Operational registers 起始虚拟地址
uint32_t rts_offset; // Runtime Register Space offset uint32_t rts_offset; // Runtime Register Space offset
uint32_t db_offset; // Doorbell offset uint32_t db_offset; // Doorbell offset
uint32_t ext_caps_off; // 扩展能力寄存器偏移量
uint8_t context_size; // 设备上下文大小 uint32_t ext_caps_off; // 扩展能力寄存器偏移量
uint16_t port_num; // 总的端口数量 uint16_t port_num; // 总的端口数量
uint8_t port_num_u2; // usb 2.0端口数量 uint8_t context_size; // 设备上下文大小
uint8_t port_num_u3; // usb 3端口数量 uint8_t port_num_u2; // usb 2.0端口数量
uint32_t page_size; // page size
uint64_t dcbaap_vaddr; // Device Context Base Address Array Pointer的虚拟地址 uint8_t port_num_u3; // usb 3端口数量
uint64_t cmd_ring_vaddr; // command ring的虚拟地址 uint8_t current_event_ring_cycle; // 当前event ring cycle
uint64_t cmd_trb_vaddr; // 下一个要写入的trb的虚拟地址 uint8_t cmd_trb_cycle; // 当前command ring cycle
uint64_t event_ring_vaddr; // event ring的虚拟地址 uint32_t page_size; // page size
uint64_t event_ring_table_vaddr; // event ring table的虚拟地址
uint64_t current_event_ring_vaddr; // 下一个要读取的event TRB的虚拟地址 uint64_t dcbaap_vaddr; // Device Context Base Address Array Pointer的虚拟地址
uint8_t cmd_trb_cycle; // 当前command ring cycle uint64_t cmd_ring_vaddr; // command ring的虚拟地址
uint8_t current_event_ring_cycle; // 当前event ring cycle uint64_t cmd_trb_vaddr; // 下一个要写入的trb的虚拟地址
struct xhci_port_info_t ports[XHCI_MAX_ROOT_HUB_PORTS]; // 指向端口信息数组的指针(由于端口offset是从1开始的因此该数组第0项为空) uint64_t event_ring_vaddr; // event ring的虚拟地址
struct xhci_ep_ring_info_t control_ep_info; // 控制端点的信息 uint64_t event_ring_table_vaddr; // event ring table的虚拟地址
uint64_t current_event_ring_vaddr; // 下一个要读取的event TRB的虚拟地址
uint64_t scratchpad_buf_array_vaddr; // 草稿行缓冲区数组的虚拟地址
struct xhci_port_info_t ports[XHCI_MAX_ROOT_HUB_PORTS]; // 指向端口信息数组的指针(由于端口offset是从1开始的因此该数组第0项为空)
struct xhci_ep_ring_info_t control_ep_info; // 控制端点的信息
}; };
// Common TRB types // Common TRB types

View File

@ -463,7 +463,9 @@ ul initial_kernel_thread(ul arg)
{ {
// kinfo("initial proc running...\targ:%#018lx", arg); // kinfo("initial proc running...\targ:%#018lx", arg);
fat32_init(); fat32_init();
usb_init(); // 使用单独的内核线程来初始化usb驱动程序
int usb_pid = kernel_thread(usb_init, 0, 0);
kinfo("LZ4 lib Version=%s", LZ4_versionString()); kinfo("LZ4 lib Version=%s", LZ4_versionString());
// 对一些组件进行单元测试 // 对一些组件进行单元测试
@ -471,21 +473,14 @@ ul initial_kernel_thread(ul arg)
ktest_start(ktest_test_bitree, 0), ktest_start(ktest_test_bitree, 0),
ktest_start(ktest_test_kfifo, 0), ktest_start(ktest_test_kfifo, 0),
ktest_start(ktest_test_mutex, 0), ktest_start(ktest_test_mutex, 0),
usb_pid,
}; };
kinfo("Waiting test thread exit..."); kinfo("Waiting test thread exit...");
// 等待测试进程退出 // 等待测试进程退出
for (int i = 0; i < sizeof(tpid) / sizeof(uint64_t); ++i) for (int i = 0; i < sizeof(tpid) / sizeof(uint64_t); ++i)
waitpid(tpid[i], NULL, NULL); waitpid(tpid[i], NULL, NULL);
kinfo("All test done."); kinfo("All test done.");
// pid_t p = fork();
// if (p == 0)
// {
// kdebug("in subproc, rflags=%#018lx", get_rflags());
// while (1)
// usleep(1000);
// }
// kdebug("subprocess pid=%d", p);
// 准备切换到用户态 // 准备切换到用户态
struct pt_regs *regs; struct pt_regs *regs;

View File

@ -26,18 +26,17 @@ void nanosleep_handler(void *pcb)
*/ */
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
{ {
int64_t total_ns = rqtp->tv_nsec;
if (total_ns < 0 || total_ns >= 1000000000) if (rqtp->tv_nsec < 0 || rqtp->tv_nsec >= 1000000000)
return -EINVAL; return -EINVAL;
// 对于小于500us的时间使用spin/rdtsc来进行定时 // 对于小于500us的时间使用spin/rdtsc来进行定时
if (total_ns < 500000) if (rqtp->tv_nsec < 500000)
{ {
kdebug("use rdtsc to nanosleep"); uint64_t expired_tsc = rdtsc() + (((uint64_t)rqtp->tv_nsec) * Cpu_tsc_freq) / 1000000000;
uint64_t expired_tsc = rdtsc() + (total_ns * Cpu_tsc_freq) / 1000000000;
while (rdtsc() < expired_tsc) while (rdtsc() < expired_tsc)
pause(); ;
if (rmtp != NULL) if (rmtp != NULL)
{ {
@ -51,7 +50,7 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
struct timer_func_list_t *sleep_task = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0); struct timer_func_list_t *sleep_task = (struct timer_func_list_t *)kmalloc(sizeof(struct timer_func_list_t), 0);
memset(sleep_task, 0, sizeof(struct timer_func_list_t)); memset(sleep_task, 0, sizeof(struct timer_func_list_t));
timer_func_init_us(sleep_task, &nanosleep_handler, (void *)current_pcb, total_ns / 1000); timer_func_init_us(sleep_task, &nanosleep_handler, (void *)current_pcb, rqtp->tv_nsec / 1000);
timer_func_add(sleep_task); timer_func_add(sleep_task);

7
run.sh
View File

@ -11,6 +11,13 @@ IA32_USE_QEMU=1
bochsrc="./bochsrc" bochsrc="./bochsrc"
ARCH="x86_64" ARCH="x86_64"
for i in "$@"
do
if [ $i == "--no-qemu" ];then
IA32_USE_QEMU=0
fi
done
if [ ${IA32_USE_QEMU} == "1" ];then if [ ${IA32_USE_QEMU} == "1" ];then
export EMULATOR=__QEMU_EMULATION__ export EMULATOR=__QEMU_EMULATION__
else else