diff --git a/api/hw/pci_device.hpp b/api/hw/pci_device.hpp index 40921708c..c0cdaf268 100644 --- a/api/hw/pci_device.hpp +++ b/api/hw/pci_device.hpp @@ -22,34 +22,47 @@ #include #include -/* PCI Register Config Space */ -#define PCI_DEV_VEND_REG 0x00 /* for the 32 bit read of dev/vend */ -#define PCI_VENDID_REG 0x00 -#define PCI_DEVID_REG 0x02 -#define PCI_CMD_REG 0x04 -#define PCI_STATUS_REG 0x06 -#define PCI_REVID_REG 0x08 -#define PCI_PROGIF_REG 0x09 -#define PCI_SUBCLASS_REG 0x0a -#define PCI_CLASS_REG 0x0b -#define PCI_CLSZ_REG 0x0c -#define PCI_LATTIM_REG 0x0d -#define PCI_HEADER_REG 0x0e -#define PCI_BIST_REG 0x0f -#define PCI_CAPABILITY_REG 0x34 - -#define PCI_COMMAND_IO 0x01 -#define PCI_COMMAND_MEM 0x02 -#define PCI_COMMAND_MASTER 0x04 - -#define PCI_CAP_ID_VNDR 0x09 -#define PCI_CAP_ID_AF 0x13 /* PCI Advanced Features */ -#define PCI_CAP_ID_MAX PCI_CAP_ID_AF -#define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */ -#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PASID - namespace PCI { + /** PCI configuration space register offsets */ + enum class config_reg : uint8_t { + DEV_VEND = 0x00, /**< 32-bit device/vendor ID */ + DEVID = 0x02, + CMD = 0x04, + STATUS = 0x06, + REVID = 0x08, + PROGIF = 0x09, + SUBCLASS = 0x0a, + CLASS = 0x0b, + CLSZ = 0x0c, + LATTIM = 0x0d, + HEADER = 0x0e, + BIST = 0x0f, + CAPABILITY = 0x34 + }; + + /** PCI command register flags */ + enum class command : uint16_t { + IO = 0x01, + MEM = 0x02, + MASTER = 0x04 + }; + + /** Standard PCI capability IDs */ + enum class cap_id : uint8_t { + MSI = 0x05, + VNDR = 0x09, + MSIX = 0x11, + AF = 0x13, /**< PCI Advanced Features */ + MAX = AF + }; + + /** Extended PCI capability IDs */ + enum class ext_cap_id : uint8_t { + PASID = 0x1B, /**< Process Address Space ID */ + MAX = PASID + }; + static const uint16_t CONFIG_ADDR {0xCF8U}; static const uint16_t CONFIG_DATA {0xCFCU}; static const uint8_t CONFIG_INTR {0x3CU}; @@ -308,7 +321,7 @@ struct msix_t; int m_iobase = -1; std::array m_resources; - std::array caps; + std::array(PCI::cap_id::MAX)+1> caps; // has msix support if not null msix_t* msix = nullptr; diff --git a/src/drivers/virtionet.cpp b/src/drivers/virtionet.cpp index b518066dd..096bc71cd 100644 --- a/src/drivers/virtionet.cpp +++ b/src/drivers/virtionet.cpp @@ -39,10 +39,29 @@ #include "virtionet.hpp" #include +#include +#include #include #include #include +extern "C" void intel_rdrand(uint64_t*); +extern "C" void intel_rdseed(uint64_t*); + +static void randomize_mac_host(uint8_t* host, size_t len, uint16_t pci_addr) +{ + uint64_t seed = pci_addr; + if (CPUID::has_feature(CPUID::Feature::RDSEED)) { + intel_rdseed(&seed); + } else if (CPUID::has_feature(CPUID::Feature::RDRAND)) { + intel_rdrand(&seed); + } else { + seed ^= __arch_system_time(); + seed ^= os::cycles_since_boot(); + } + memcpy(host, &seed, len); +} + //#define NO_DEFERRED_KICK #ifndef NO_DEFERRED_KICK #include @@ -173,6 +192,17 @@ VirtioNet::VirtioNet(hw::PCI_Device& d, const uint16_t /*mtu*/) // Getting the MAC + status get_config(); + // Randomize the host-specific part so multiple local instances + // don't end up with the same virtio-net address. + { + uint8_t addr[MAC::Addr::PARTS_LEN]; + memcpy(addr, _conf.mac.part, sizeof(addr)); + addr[0] = (addr[0] & 0xfc) | 0x02; + randomize_mac_host(&addr[3], 3, m_pcidev.pci_addr()); + _conf.mac = MAC::Addr(addr[0], addr[1], addr[2], + addr[3], addr[4], addr[5]); + } + CHECK(_conf.mac.major > 0, "Valid Mac address: %s", _conf.mac.str().c_str()); diff --git a/src/hw/pci_device.cpp b/src/hw/pci_device.cpp index 508ffea81..1dab1bb73 100644 --- a/src/hw/pci_device.cpp +++ b/src/hw/pci_device.cpp @@ -90,9 +90,11 @@ namespace hw { : pci_addr_{pci_addr}, device_id_{device_id} { // set master, mem and io flags - uint32_t cmd = read32(PCI_CMD_REG); - cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEM | PCI_COMMAND_IO; - write_dword(PCI_CMD_REG, cmd); + uint32_t cmd = read32(static_cast(PCI::config_reg::CMD)); + cmd |= static_cast(PCI::command::MASTER) + | static_cast(PCI::command::MEM) + | static_cast(PCI::command::IO); + write_dword(static_cast(PCI::config_reg::CMD), cmd); // device class info is coming from pci manager to save a PCI read this->devtype_.reg = devclass; @@ -167,11 +169,11 @@ namespace hw { caps = {}; // the capability list is only available if bit 4 // in the status register is set - uint16_t status = read16(PCI_STATUS_REG); + uint16_t status = read16(static_cast(PCI::config_reg::STATUS)); //printf("read16 %#x status %#x\n", PCI_STATUS_REG, status); if ((status & 0x10) == 0) return; // this offset works for non-cardbus bridges - uint32_t offset = PCI_CAPABILITY_REG; + uint32_t offset = static_cast(PCI::config_reg::CAPABILITY); // read first capability offset = read16(offset) & 0xff; offset &= ~0x3; // lower 2 bits reserved @@ -189,19 +191,19 @@ namespace hw { void PCI_Device::deactivate() { // disables device (except for configuration) - write_dword(PCI_CMD_REG, 0); + write_dword(static_cast(PCI::config_reg::CMD), 0); } void PCI_Device::intx_enable() { - auto cmd = read16(PCI_CMD_REG); - write16(PCI_CMD_REG, cmd & ~(1 << 10)); + auto cmd = read16(static_cast(PCI::config_reg::CMD)); + write16(static_cast(PCI::config_reg::CMD), cmd & ~(1 << 10)); // delete msi-x if (this->msix) delete this->msix; } bool PCI_Device::intx_status() { - auto stat = read16(PCI_STATUS_REG); + auto stat = read16(static_cast(PCI::config_reg::STATUS)); return stat & (1 << 3); } diff --git a/src/hw/pci_msi.cpp b/src/hw/pci_msi.cpp index 358aa3e25..de7c34b2e 100644 --- a/src/hw/pci_msi.cpp +++ b/src/hw/pci_msi.cpp @@ -2,12 +2,6 @@ #include #include -#define PCI_CMD_REG 0x04 - -// MSI and MSI-X capability registers -#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ -#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */ - // Message Signalled Interrupts registers #define PCI_MSI_FLAGS_ENABLE 0x0001 /* MSI feature enabled */ #define PCI_MSI_FLAGS_QMASK 0x000e /* Maximum queue size available */ @@ -30,20 +24,20 @@ namespace hw { int PCI_Device::msi_cap() { - return caps[PCI_CAP_ID_MSI]; + return caps[static_cast(PCI::cap_id::MSI)]; } int PCI_Device::msix_cap() { - return caps[PCI_CAP_ID_MSIX]; + return caps[static_cast(PCI::cap_id::MSIX)]; } void PCI_Device::init_msix() { assert(this->msix == nullptr); // disable intx - auto cmd = read16(PCI_CMD_REG); - write16(PCI_CMD_REG, cmd | (1 << 10)); + auto cmd = read16(static_cast(PCI::config_reg::CMD)); + write16(static_cast(PCI::config_reg::CMD), cmd | (1 << 10)); // enable MSI-X this->msix = new msix_t(*this, msix_cap()); // deallocate if it failed diff --git a/src/platform/x86_pc/apic_revenant.cpp b/src/platform/x86_pc/apic_revenant.cpp index 02cc18aa7..526130d4a 100644 --- a/src/platform/x86_pc/apic_revenant.cpp +++ b/src/platform/x86_pc/apic_revenant.cpp @@ -3,6 +3,7 @@ #include "apic_timer.hpp" #include "clocks.hpp" #include "idt.hpp" +#include "init_libc.hpp" #include //#include #include @@ -90,6 +91,7 @@ void revenant_main(int cpu) SMP::global_unlock(); // initialize exceptions before asserts x86::idt_initialize_for_cpu(cpu); + x86::init_syscall_trap(); assert(cpu == SMP::cpu_id()); assert(stack >= this_stack_end && stack < this_stack); // relates to [[maybe_unused]] diff --git a/src/platform/x86_pc/init_libc.cpp b/src/platform/x86_pc/init_libc.cpp index ae39c919a..154f8101a 100644 --- a/src/platform/x86_pc/init_libc.cpp +++ b/src/platform/x86_pc/init_libc.cpp @@ -153,18 +153,8 @@ namespace x86 aux[i++].set_long(AT_NULL, 0); #ifdef PLATFORM_x86_pc - // SYSCALL instruction - #if defined(__x86_64__) - KDEBUG("* Initialize syscall MSR (64-bit)\n"); - uint64_t star_kernel_cs = 8ull << 32; - uint64_t star_user_cs = 8ull << 48; - uint64_t star = star_kernel_cs | star_user_cs; - x86::CPU::write_msr(IA32_STAR, star); - x86::CPU::write_msr(IA32_LSTAR, (uintptr_t)&__syscall_entry); - #elif defined(__i386__) - KDEBUG("Initialize syscall intr (32-bit)\n"); - #warning Classical syscall interface missing for 32-bit - #endif + KDEBUG("* Initialize syscall trap\n"); + x86::init_syscall_trap(); #endif // GDB_ENTRY; @@ -173,3 +163,16 @@ namespace x86 __libc_start_main(kernel_main, argc, argv.data()); } } + +void x86::init_syscall_trap() +{ +#if defined(PLATFORM_x86_pc) && defined(__x86_64__) + uint64_t star_kernel_cs = 8ull << 32; + uint64_t star_user_cs = 8ull << 48; + uint64_t star = star_kernel_cs | star_user_cs; + x86::CPU::write_msr(IA32_STAR, star); + x86::CPU::write_msr(IA32_LSTAR, (uintptr_t)&__syscall_entry); +#elif defined(PLATFORM_x86_pc) && defined(__i386__) + #warning Classical syscall interface missing for 32-bit +#endif +} diff --git a/src/platform/x86_pc/init_libc.hpp b/src/platform/x86_pc/init_libc.hpp index c71daa908..2e92aa2b4 100644 --- a/src/platform/x86_pc/init_libc.hpp +++ b/src/platform/x86_pc/init_libc.hpp @@ -4,6 +4,7 @@ namespace x86 { extern void init_libc(uint32_t magic, uint32_t address); + void init_syscall_trap(); } extern "C" {