Compare commits

...

3 Commits

Author SHA1 Message Date
Bananymous 4b917390ac Kernel: Fix sse state saving
This was broken when I added SMP support. This patch makes sse kind of
dumb as it is saved and restored on every interrupt, but now it at least
works properly... I'll have to look into how sse can get optimized
nicely with SMP. Simple way would be pinning each thread to a specific
processor and doing pretty much what I had before, but sse thread saved
in processor rather than static global.
2024-07-16 23:15:11 +03:00
Bananymous 7a0fb9a57f Kernel: Fix TTY scroll clearing first and/or last characters from line 2024-07-16 22:49:49 +03:00
Bananymous 58fcd2b2fe Kernel: Fix multi-interface USB device initialization 2024-07-16 22:29:18 +03:00
8 changed files with 56 additions and 93 deletions

View File

@ -8,7 +8,8 @@
"${workspaceFolder}/userspace/libraries/*/include" "${workspaceFolder}/userspace/libraries/*/include"
], ],
"defines": [ "defines": [
"__arch=x86_64" "__arch=x86_64",
"__enable_sse=1"
], ],
"compilerPath": "${workspaceFolder}/toolchain/local/bin/x86_64-banan_os-gcc", "compilerPath": "${workspaceFolder}/toolchain/local/bin/x86_64-banan_os-gcc",
"cStandard": "c17", "cStandard": "c17",
@ -24,7 +25,8 @@
], ],
"defines": [ "defines": [
"__arch=x86_64", "__arch=x86_64",
"__is_kernel" "__is_kernel",
"__enable_sse=1"
], ],
"compilerPath": "${workspaceFolder}/toolchain/local/bin/x86_64-banan_os-gcc", "compilerPath": "${workspaceFolder}/toolchain/local/bin/x86_64-banan_os-gcc",
"cStandard": "c17", "cStandard": "c17",

View File

@ -82,7 +82,6 @@ namespace Kernel
#if __enable_sse #if __enable_sse
void save_sse(); void save_sse();
void load_sse(); void load_sse();
static Thread* sse_thread();
#endif #endif
void add_mutex() { m_mutex_count++; } void add_mutex() { m_mutex_count++; }

View File

@ -75,12 +75,12 @@ namespace Kernel
}; };
public: public:
static BAN::ErrorOr<BAN::UniqPtr<USBHIDDriver>> create(USBDevice&, const USBDevice::InterfaceDescriptor&, uint8_t interface_index); static BAN::ErrorOr<BAN::UniqPtr<USBHIDDriver>> create(USBDevice&, const USBDevice::InterfaceDescriptor&);
void handle_input_data(BAN::ConstByteSpan, uint8_t endpoint_id) override; void handle_input_data(BAN::ConstByteSpan, uint8_t endpoint_id) override;
private: private:
USBHIDDriver(USBDevice&, const USBDevice::InterfaceDescriptor&, uint8_t interface_index); USBHIDDriver(USBDevice&, const USBDevice::InterfaceDescriptor&);
~USBHIDDriver(); ~USBHIDDriver();
BAN::ErrorOr<void> initialize(); BAN::ErrorOr<void> initialize();
@ -90,7 +90,6 @@ namespace Kernel
private: private:
USBDevice& m_device; USBDevice& m_device;
USBDevice::InterfaceDescriptor m_interface; USBDevice::InterfaceDescriptor m_interface;
const uint8_t m_interface_index;
bool m_uses_report_id { false }; bool m_uses_report_id { false };
BAN::Vector<DeviceReport> m_device_inputs; BAN::Vector<DeviceReport> m_device_inputs;

View File

@ -173,6 +173,10 @@ namespace Kernel
if (tid) if (tid)
{ {
#if __enable_sse
Thread::current().save_sse();
#endif
if (isr == ISR::PageFault) if (isr == ISR::PageFault)
{ {
// Check if stack is OOB // Check if stack is OOB
@ -218,31 +222,6 @@ namespace Kernel
} }
} }
} }
#if __enable_sse
else if (isr == ISR::DeviceNotAvailable)
{
#if ARCH(x86_64)
asm volatile(
"movq %cr0, %rax;"
"andq $~(1 << 3), %rax;"
"movq %rax, %cr0;"
);
#elif ARCH(i686)
asm volatile(
"movl %cr0, %eax;"
"andl $~(1 << 3), %eax;"
"movl %eax, %cr0;"
);
#endif
if (auto* current = &Thread::current(); current != Thread::sse_thread())
{
if (auto* sse = Thread::sse_thread())
sse->save_sse();
current->load_sse();
}
goto done;
}
#endif
} }
Debug::s_debug_lock.lock(); Debug::s_debug_lock.lock();
@ -334,7 +313,11 @@ namespace Kernel
ASSERT(Thread::current().state() != Thread::State::Terminated); ASSERT(Thread::current().state() != Thread::State::Terminated);
done: done:
#if __enable_sse
Thread::current().load_sse();
#else
return; return;
#endif
} }
extern "C" void cpp_yield_handler(InterruptStack* interrupt_stack, InterruptRegisters* interrupt_registers) extern "C" void cpp_yield_handler(InterruptStack* interrupt_stack, InterruptRegisters* interrupt_registers)
@ -357,6 +340,10 @@ done:
asm volatile("cli; 1: hlt; jmp 1b"); asm volatile("cli; 1: hlt; jmp 1b");
} }
#if __enable_sse
Thread::current().save_sse();
#endif
if (!InterruptController::get().is_in_service(irq)) if (!InterruptController::get().is_in_service(irq))
dprintln("spurious irq 0x{2H}", irq); dprintln("spurious irq 0x{2H}", irq);
else else
@ -377,6 +364,10 @@ done:
Scheduler::get().reschedule_if_idling(); Scheduler::get().reschedule_if_idling();
ASSERT(Thread::current().state() != Thread::State::Terminated); ASSERT(Thread::current().state() != Thread::State::Terminated);
#if __enable_sse
Thread::current().load_sse();
#endif
} }
void IDT::register_interrupt_handler(uint8_t index, void (*handler)()) void IDT::register_interrupt_handler(uint8_t index, void (*handler)())

View File

@ -364,6 +364,10 @@ namespace Kernel
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
} }
bool old_show_cursor = m_show_cursor;
m_show_cursor = false;
set_cursor_position(m_column, m_row);
switch (codepoint) switch (codepoint)
{ {
case BEL: // TODO case BEL: // TODO
@ -410,10 +414,6 @@ namespace Kernel
for (uint32_t x = 0; x < m_width; x++) for (uint32_t x = 0; x < m_width; x++)
m_buffer[(m_height - 1) * m_width + x] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' }; m_buffer[(m_height - 1) * m_width + x] = { .foreground = m_foreground, .background = m_background, .codepoint = ' ' };
// hide cursor during scrolling
bool old_show_cursor = m_show_cursor;
m_show_cursor = false;
set_cursor_position(0, 0);
if (!m_terminal_driver->scroll(m_background)) if (!m_terminal_driver->scroll(m_background))
{ {
// No fast scrolling, render the whole buffer to the screen // No fast scrolling, render the whole buffer to the screen
@ -421,12 +421,12 @@ namespace Kernel
for (uint32_t x = 0; x < m_width; x++) for (uint32_t x = 0; x < m_width; x++)
render_from_buffer(x, y); render_from_buffer(x, y);
} }
m_show_cursor = old_show_cursor;
m_column = 0; m_column = 0;
m_row--; m_row--;
} }
m_show_cursor = old_show_cursor;
set_cursor_position(m_column, m_row); set_cursor_position(m_column, m_row);
} }

View File

@ -113,33 +113,8 @@ namespace Kernel
: m_tid(tid), m_process(process) : m_tid(tid), m_process(process)
{ {
#if __enable_sse #if __enable_sse
#if ARCH(x86_64) // initializes sse storage to valid state
uintptr_t cr0;
asm volatile(
"movq %%cr0, %%rax;"
"movq %%rax, %[cr0];"
"andq $~(1 << 3), %%rax;"
"movq %%rax, %%cr0;"
: [cr0]"=r"(cr0)
:: "rax"
);
save_sse(); save_sse();
asm volatile("movq %0, %%cr0" :: "r"(cr0));
#elif ARCH(i686)
uintptr_t cr0;
asm volatile(
"movl %%cr0, %%eax;"
"movl %%eax, %[cr0];"
"andl $~(1 << 3), %%eax;"
"movl %%eax, %%cr0;"
: [cr0]"=r"(cr0)
:: "eax"
);
save_sse();
asm volatile("movl %0, %%cr0" :: "r"(cr0));
#else
#error
#endif
#endif #endif
} }
@ -482,8 +457,6 @@ namespace Kernel
} }
#if __enable_sse #if __enable_sse
static Thread* s_sse_thread = nullptr;
void Thread::save_sse() void Thread::save_sse()
{ {
asm volatile("fxsave %0" :: "m"(m_sse_storage)); asm volatile("fxsave %0" :: "m"(m_sse_storage));
@ -492,12 +465,6 @@ namespace Kernel
void Thread::load_sse() void Thread::load_sse()
{ {
asm volatile("fxrstor %0" :: "m"(m_sse_storage)); asm volatile("fxrstor %0" :: "m"(m_sse_storage));
s_sse_thread = this;
}
Thread* Thread::sse_thread()
{
return s_sse_thread;
} }
#endif #endif

View File

@ -140,10 +140,8 @@ namespace Kernel
TRY(send_request(request, 0)); TRY(send_request(request, 0));
} }
for (size_t j = 0; j < configuration.interfaces.size(); j++) for (const auto& interface : configuration.interfaces)
{ {
const auto& interface = configuration.interfaces[j];
switch (static_cast<USB::InterfaceBaseClass>(interface.descriptor.bInterfaceClass)) switch (static_cast<USB::InterfaceBaseClass>(interface.descriptor.bInterfaceClass))
{ {
case USB::InterfaceBaseClass::Audio: case USB::InterfaceBaseClass::Audio:
@ -153,7 +151,7 @@ namespace Kernel
dprintln_if(DEBUG_USB, "Found CommunicationAndCDCControl interface"); dprintln_if(DEBUG_USB, "Found CommunicationAndCDCControl interface");
break; break;
case USB::InterfaceBaseClass::HID: case USB::InterfaceBaseClass::HID:
if (auto result = USBHIDDriver::create(*this, interface, j); !result.is_error()) if (auto result = USBHIDDriver::create(*this, interface); !result.is_error())
TRY(m_class_drivers.push_back(result.release_value())); TRY(m_class_drivers.push_back(result.release_value()));
break; break;
case USB::InterfaceBaseClass::Physical: case USB::InterfaceBaseClass::Physical:
@ -217,14 +215,17 @@ namespace Kernel
dprintln_if(DEBUG_USB, "Invalid interface base class {2H}", interface.descriptor.bInterfaceClass); dprintln_if(DEBUG_USB, "Invalid interface base class {2H}", interface.descriptor.bInterfaceClass);
break; break;
} }
}
if (!m_class_drivers.empty()) if (!m_class_drivers.empty())
{ {
dprintln("Successfully initialized USB interface"); dprintln("Successfully initialized USB device with {}/{} interfaces",
m_class_drivers.size(),
configuration.interfaces.size()
);
return {}; return {};
} }
} }
}
return BAN::Error::from_errno(ENOTSUP); return BAN::Error::from_errno(ENOTSUP);
} }

View File

@ -11,6 +11,11 @@
namespace Kernel namespace Kernel
{ {
enum HIDRequest : uint8_t
{
SET_PROTOCOL = 0x0B,
};
enum class HIDDescriptorType : uint8_t enum class HIDDescriptorType : uint8_t
{ {
HID = 0x21, HID = 0x21,
@ -64,17 +69,16 @@ namespace Kernel
static BAN::ErrorOr<BAN::Vector<Collection>> parse_report_descriptor(BAN::ConstByteSpan report_data, bool& out_use_report_id); static BAN::ErrorOr<BAN::Vector<Collection>> parse_report_descriptor(BAN::ConstByteSpan report_data, bool& out_use_report_id);
BAN::ErrorOr<BAN::UniqPtr<USBHIDDriver>> USBHIDDriver::create(USBDevice& device, const USBDevice::InterfaceDescriptor& interface, uint8_t interface_index) BAN::ErrorOr<BAN::UniqPtr<USBHIDDriver>> USBHIDDriver::create(USBDevice& device, const USBDevice::InterfaceDescriptor& interface)
{ {
auto result = TRY(BAN::UniqPtr<USBHIDDriver>::create(device, interface, interface_index)); auto result = TRY(BAN::UniqPtr<USBHIDDriver>::create(device, interface));
TRY(result->initialize()); TRY(result->initialize());
return result; return result;
} }
USBHIDDriver::USBHIDDriver(USBDevice& device, const USBDevice::InterfaceDescriptor& interface, uint8_t interface_index) USBHIDDriver::USBHIDDriver(USBDevice& device, const USBDevice::InterfaceDescriptor& interface)
: m_device(device) : m_device(device)
, m_interface(interface) , m_interface(interface)
, m_interface_index(interface_index)
{} {}
USBHIDDriver::~USBHIDDriver() USBHIDDriver::~USBHIDDriver()
@ -119,18 +123,17 @@ namespace Kernel
} }
// If this device supports boot protocol, make sure it is not used // If this device supports boot protocol, make sure it is not used
if (m_interface.endpoints.front().descriptor.bDescriptorType & 0x80) if (m_interface.descriptor.bInterfaceSubClass == 0x01)
{ {
USBDeviceRequest request; USBDeviceRequest request;
request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Class | USB::RequestType::Interface; request.bmRequestType = USB::RequestType::HostToDevice | USB::RequestType::Class | USB::RequestType::Interface;
request.bRequest = USB::Request::SET_INTERFACE; request.bRequest = HIDRequest::SET_PROTOCOL;
request.wValue = 1; // report protocol request.wValue = 1; // report protocol
request.wIndex = m_interface_index; request.wIndex = m_interface.descriptor.bInterfaceNumber;
request.wLength = 0; request.wLength = 0;
TRY(m_device.send_request(request, 0)); TRY(m_device.send_request(request, 0));
} }
const auto& hid_descriptor = *reinterpret_cast<const HIDDescriptor*>(m_interface.misc_descriptors[hid_descriptor_index].data()); const auto& hid_descriptor = *reinterpret_cast<const HIDDescriptor*>(m_interface.misc_descriptors[hid_descriptor_index].data());
dprintln_if(DEBUG_HID, "HID descriptor ({} bytes)", m_interface.misc_descriptors[hid_descriptor_index].size()); dprintln_if(DEBUG_HID, "HID descriptor ({} bytes)", m_interface.misc_descriptors[hid_descriptor_index].size());
dprintln_if(DEBUG_HID, " bLength: {}", hid_descriptor.bLength); dprintln_if(DEBUG_HID, " bLength: {}", hid_descriptor.bLength);
@ -139,6 +142,7 @@ namespace Kernel
dprintln_if(DEBUG_HID, " bCountryCode: {}", hid_descriptor.bCountryCode); dprintln_if(DEBUG_HID, " bCountryCode: {}", hid_descriptor.bCountryCode);
dprintln_if(DEBUG_HID, " bNumDescriptors: {}", hid_descriptor.bNumDescriptors); dprintln_if(DEBUG_HID, " bNumDescriptors: {}", hid_descriptor.bNumDescriptors);
uint32_t report_descriptor_index = 0;
BAN::Vector<Collection> collections; BAN::Vector<Collection> collections;
for (size_t i = 0; i < hid_descriptor.bNumDescriptors; i++) for (size_t i = 0; i < hid_descriptor.bNumDescriptors; i++)
{ {
@ -160,8 +164,8 @@ namespace Kernel
USBDeviceRequest request; USBDeviceRequest request;
request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Standard | USB::RequestType::Interface; request.bmRequestType = USB::RequestType::DeviceToHost | USB::RequestType::Standard | USB::RequestType::Interface;
request.bRequest = USB::Request::GET_DESCRIPTOR; request.bRequest = USB::Request::GET_DESCRIPTOR;
request.wValue = static_cast<uint16_t>(HIDDescriptorType::Report) << 8; request.wValue = (static_cast<uint16_t>(HIDDescriptorType::Report) << 8) | report_descriptor_index++;
request.wIndex = m_interface_index; request.wIndex = m_interface.descriptor.bInterfaceNumber;
request.wLength = descriptor.wItemLength; request.wLength = descriptor.wItemLength;
auto transferred = TRY(m_device.send_request(request, dma_buffer->paddr())); auto transferred = TRY(m_device.send_request(request, dma_buffer->paddr()));