Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 40 additions & 27 deletions api/hw/pci_device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,34 +22,47 @@
#include <vector>
#include <unordered_map>

/* 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};
Expand Down Expand Up @@ -308,7 +321,7 @@ struct msix_t;
int m_iobase = -1;
std::array<PCI::Resource, 6> m_resources;

std::array<pcicap_t, PCI_CAP_ID_MAX+1> caps;
std::array<pcicap_t, static_cast<size_t>(PCI::cap_id::MAX)+1> caps;

// has msix support if not null
msix_t* msix = nullptr;
Expand Down
30 changes: 30 additions & 0 deletions src/drivers/virtionet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,29 @@

#include "virtionet.hpp"
#include <kernel/events.hpp>
#include <kernel/cpuid.hpp>
#include <arch.hpp>
#include <malloc.h>
#include <cstring>
#include <info>

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 <smp>
Expand Down Expand Up @@ -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());

Expand Down
20 changes: 11 additions & 9 deletions src/hw/pci_device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<uint8_t>(PCI::config_reg::CMD));
cmd |= static_cast<uint32_t>(PCI::command::MASTER)
| static_cast<uint32_t>(PCI::command::MEM)
| static_cast<uint32_t>(PCI::command::IO);
write_dword(static_cast<uint8_t>(PCI::config_reg::CMD), cmd);

// device class info is coming from pci manager to save a PCI read
this->devtype_.reg = devclass;
Expand Down Expand Up @@ -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<uint8_t>(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<uint8_t>(PCI::config_reg::CAPABILITY);
// read first capability
offset = read16(offset) & 0xff;
offset &= ~0x3; // lower 2 bits reserved
Expand All @@ -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<uint8_t>(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<uint8_t>(PCI::config_reg::CMD));
write16(static_cast<uint8_t>(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<uint8_t>(PCI::config_reg::STATUS));
return stat & (1 << 3);
}

Expand Down
14 changes: 4 additions & 10 deletions src/hw/pci_msi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,6 @@
#include <hw/pci.hpp>
#include <hw/msi.hpp>

#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 */
Expand All @@ -30,20 +24,20 @@ namespace hw
{
int PCI_Device::msi_cap()
{
return caps[PCI_CAP_ID_MSI];
return caps[static_cast<size_t>(PCI::cap_id::MSI)];
}

int PCI_Device::msix_cap()
{
return caps[PCI_CAP_ID_MSIX];
return caps[static_cast<size_t>(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<uint8_t>(PCI::config_reg::CMD));
write16(static_cast<uint8_t>(PCI::config_reg::CMD), cmd | (1 << 10));
// enable MSI-X
this->msix = new msix_t(*this, msix_cap());
// deallocate if it failed
Expand Down
2 changes: 2 additions & 0 deletions src/platform/x86_pc/apic_revenant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "apic_timer.hpp"
#include "clocks.hpp"
#include "idt.hpp"
#include "init_libc.hpp"
#include <kernel/events.hpp>
//#include <kernel/os.hpp>
#include <os.hpp>
Expand Down Expand Up @@ -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]]

Expand Down
27 changes: 15 additions & 12 deletions src/platform/x86_pc/init_libc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
}
1 change: 1 addition & 0 deletions src/platform/x86_pc/init_libc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace x86
{
extern void init_libc(uint32_t magic, uint32_t address);
void init_syscall_trap();
}

extern "C" {
Expand Down