Skip to content

Commit

Permalink
Merge pull request #303 from xvanc/trunk
Browse files Browse the repository at this point in the history
riscv: implement extension detection and support for `Svpbmt`
  • Loading branch information
mintsuki authored Sep 15, 2023
2 parents 4470aa0 + 1352a63 commit 7326a3d
Show file tree
Hide file tree
Showing 11 changed files with 434 additions and 154 deletions.
13 changes: 13 additions & 0 deletions common/entry.s3.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <drivers/disk.h>
#include <sys/lapic.h>
#include <lib/readline.h>
#include <sys/cpu.h>

void stage3_common(void);

Expand Down Expand Up @@ -130,6 +131,18 @@ noreturn void stage3_common(void) {
init_io_apics();
#endif

#if defined (__riscv)
#if defined (UEFI)
RISCV_EFI_BOOT_PROTOCOL *rv_proto = get_riscv_boot_protocol();
if (rv_proto == NULL || rv_proto->GetBootHartId(rv_proto, &bsp_hartid) != EFI_SUCCESS) {
panic(false, "failed to get BSP's hartid");
}
#else
#error riscv: only UEFI is supported
#endif
init_riscv();
#endif

term_notready();

menu(true);
Expand Down
69 changes: 69 additions & 0 deletions common/lib/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,75 @@ struct smbios_entry_point_64 {
uint64_t table_address;
} __attribute__((packed));

struct madt {
struct sdt header;
uint32_t local_controller_addr;
uint32_t flags;
char madt_entries_begin[];
} __attribute__((packed));

struct madt_header {
uint8_t type;
uint8_t length;
} __attribute__((packed));

struct madt_lapic {
struct madt_header header;
uint8_t acpi_processor_uid;
uint8_t lapic_id;
uint32_t flags;
} __attribute__((packed));

struct madt_x2apic {
struct madt_header header;
uint8_t reserved[2];
uint32_t x2apic_id;
uint32_t flags;
uint32_t acpi_processor_uid;
} __attribute__((packed));

struct madt_io_apic {
uint8_t type;
uint8_t length;
uint8_t apic_id;
uint8_t reserved;
uint32_t address;
uint32_t gsib;
} __attribute__((packed));

struct madt_gicc {
struct madt_header header;
uint8_t reserved1[2];
uint32_t iface_no;
uint32_t acpi_uid;
uint32_t flags;
uint32_t parking_ver;
uint32_t perf_gsiv;
uint64_t parking_addr;
uint64_t gicc_base_addr;
uint64_t gicv_base_addr;
uint64_t gich_base_addr;
uint32_t vgic_maint_gsiv;
uint64_t gicr_base_addr;
uint64_t mpidr;
uint8_t power_eff_class;
uint8_t reserved2;
uint16_t spe_overflow_gsiv;
} __attribute__((packed));

// Reference: https://github.com/riscv-non-isa/riscv-acpi/issues/15
struct madt_riscv_intc {
struct madt_header header;
uint8_t version;
uint8_t reserved;
uint32_t flags;
uint64_t hartid;
uint32_t acpi_processor_uid;
} __attribute__((packed));

#define MADT_RISCV_INTC_ENABLED ((uint32_t)1 << 0)
#define MADT_RISCV_INTC_ONLINE_CAPABLE ((uint32_t)1 << 1)

uint8_t acpi_checksum(void *ptr, size_t size);
void *acpi_get_rsdp(void);

Expand Down
3 changes: 3 additions & 0 deletions common/lib/libc.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

bool isprint(int c);
bool isspace(int c);
bool isalpha(int c);
bool isdigit(int c);

int toupper(int c);
int tolower(int c);
Expand All @@ -23,6 +25,7 @@ size_t strlen(const char *);
int strcmp(const char *, const char *);
int strcasecmp(const char *, const char *);
int strncmp(const char *, const char *, size_t);
int strncasecmp(const char *, const char *, size_t);
int inet_pton(const char *src, void *dst);

#endif
20 changes: 20 additions & 0 deletions common/lib/libc.s2.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@ bool isspace(int c) {
return (c >= '\t' && c <= 0xD) || c == ' ';
}

bool isalpha(int c) {
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}

bool isdigit(int c) {
return c >= '0' && c <= '9';
}

int toupper(int c) {
if (c >= 'a' && c <= 'z') {
return c - 0x20;
Expand Down Expand Up @@ -84,6 +92,18 @@ int strncmp(const char *s1, const char *s2, size_t n) {
return 0;
}

int strncasecmp(const char *s1, const char *s2, size_t n) {
for (size_t i = 0; i < n; i++) {
char c1 = s1[i], c2 = s2[i];
if (tolower(c1) != tolower(c2))
return c1 < c2 ? -1 : 1;
if (!c1)
return 0;
}

return 0;
}

size_t strlen(const char *str) {
size_t len;

Expand Down
13 changes: 13 additions & 0 deletions common/mm/vmm.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_
#define PT_FLAG_USER ((uint64_t)1 << 4)
#define PT_FLAG_ACCESSED ((uint64_t)1 << 6)
#define PT_FLAG_DIRTY ((uint64_t)1 << 7)
#define PT_FLAG_PBMT_NC ((uint64_t)1 << 62)
#define PT_PADDR_MASK ((uint64_t)0x003ffffffffffc00)

#define PT_FLAG_RWX (PT_FLAG_READ | PT_FLAG_WRITE | PT_FLAG_EXEC)
Expand All @@ -271,6 +272,8 @@ static uint64_t pt_to_vmm_flags_internal(pt_entry_t entry) {
flags |= VMM_FLAG_WRITE;
if (!(entry & PT_FLAG_EXEC))
flags |= VMM_FLAG_NOEXEC;
if (entry & PT_FLAG_PBMT_NC)
flags |= VMM_FLAG_FB;

return flags;
}
Expand Down Expand Up @@ -337,11 +340,19 @@ int vmm_max_paging_mode(void)
return 6 + max_level;
}

static pt_entry_t pbmt_nc = 0;

pagemap_t new_pagemap(int paging_mode) {
pagemap_t pagemap;
pagemap.paging_mode = paging_mode;
pagemap.max_page_size = paging_mode - 6;
pagemap.top_level = ext_mem_alloc(PT_SIZE);

if (riscv_check_isa_extension("svpbmt", NULL, NULL)) {
printv("riscv: Svpbmt extension is supported.\n");
pbmt_nc = PT_FLAG_PBMT_NC;
}

return pagemap;
}

Expand All @@ -357,6 +368,8 @@ void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_
ptflags |= PT_FLAG_WRITE;
if (!(flags & VMM_FLAG_NOEXEC))
ptflags |= PT_FLAG_EXEC;
if (flags & VMM_FLAG_FB)
ptflags |= pbmt_nc;

// Start at the highest level.
// The values of `enum page_size` map to the level index at which that size is mapped.
Expand Down
20 changes: 1 addition & 19 deletions common/protos/limine.c
Original file line number Diff line number Diff line change
Expand Up @@ -923,19 +923,6 @@ FEAT_END
pagemap = build_pagemap(paging_mode, nx_available, ranges, ranges_count,
physical_base, virtual_base, direct_map_offset);

#if defined (__riscv64)
// Fetch the BSP's Hart ID before exiting boot services.
size_t bsp_hartid;
bool have_bsp_hartid = false;

RISCV_EFI_BOOT_PROTOCOL *riscv_boot_proto = get_riscv_boot_protocol();
if (riscv_boot_proto != NULL) {
if (riscv_boot_proto->GetBootHartId(riscv_boot_proto, &bsp_hartid) == EFI_SUCCESS) {
have_bsp_hartid = true;
}
}
#endif

#if defined (UEFI)
efi_exit_boot_services();
#endif
Expand All @@ -962,12 +949,7 @@ FEAT_START
pagemap, LIMINE_MAIR(fb_attr), LIMINE_TCR(tsz, pa), LIMINE_SCTLR,
direct_map_offset);
#elif defined (__riscv64)
if (!have_bsp_hartid) {
printv("smp: failed to get bsp's hart id\n");
break;
}

smp_info = init_smp(&cpu_count, bsp_hartid, pagemap, direct_map_offset);
smp_info = init_smp(&cpu_count, pagemap, direct_map_offset);
#else
#error Unknown architecture
#endif
Expand Down
24 changes: 24 additions & 0 deletions common/sys/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,30 @@ inline uint64_t rdtsc(void) {
locked_read__ret; \
})

extern size_t bsp_hartid;

struct riscv_hart {
struct riscv_hart *next;
const char *isa_string;
size_t hartid;
uint32_t acpi_uid;
uint8_t mmu_type;
uint8_t flags;
};

#define RISCV_HART_COPROC ((uint8_t)1 << 0) // is a coprocessor
#define RISCV_HART_HAS_MMU ((uint8_t)1 << 1) // `mmu_type` field is valid

extern struct riscv_hart *hart_list;

bool riscv_check_isa_extension_for(size_t hartid, const char *ext, size_t *maj, size_t *min);

static inline bool riscv_check_isa_extension(const char *ext, size_t *maj, size_t *min) {
return riscv_check_isa_extension_for(bsp_hartid, ext, maj, min);
}

void init_riscv(void);

#else
#error Unknown architecture
#endif
Expand Down
Loading

0 comments on commit 7326a3d

Please sign in to comment.