Skip to content

Commit

Permalink
arch,pt: unify and standardize vmap API interface
Browse files Browse the repository at this point in the history
Summary of the changes:
  * Get rid of kmap() API - it was confusing and non-standard
  * Add set of generic vmap APIs and make them public
      - These functions allow to specify all parameters
          * All level PT flags
          * Address space (via CR3 pointer)
  * Add set of order-specific (4K, 2M, 1G) public vmap APIs
      - Use default PT flags for non-last level
      - Allow to propagate user bit on request
  * Add separate sets of APIs for kernel and user address spaces
  * Move all interface definitions from page.h to pagetable.h

Signed-off-by: Pawel Wieczorkiewicz <[email protected]>
  • Loading branch information
wipawel committed Nov 23, 2023
1 parent 26ea541 commit 4b429f3
Show file tree
Hide file tree
Showing 17 changed files with 202 additions and 127 deletions.
3 changes: 2 additions & 1 deletion arch/x86/apic.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <cpu.h>
#include <ktf.h>
#include <lib.h>
#include <pagetable.h>
#include <percpu.h>
#include <processor.h>
#include <time.h>
Expand Down Expand Up @@ -160,7 +161,7 @@ void init_apic(unsigned int cpu_id, apic_mode_t mode) {
* X2APIC uses MSRs for accesses, so no mapping needed.
*/
if (apic_mode == APIC_MODE_XAPIC)
vmap_4k(apic_get_base(apic_base), apic_base.base, L1_PROT_NOCACHE);
vmap_kern_4k(apic_get_base(apic_base), apic_base.base, L1_PROT_NOCACHE);

spiv.reg = apic_read(APIC_SPIV);
spiv.vector = APIC_SPI_VECTOR;
Expand Down
5 changes: 3 additions & 2 deletions arch/x86/boot/multiboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <errno.h>
#include <mm/pmm.h>
#include <multiboot2.h>
#include <pagetable.h>

#define TAG_ADDR(tag) \
((multiboot2_tag_t *) ((multiboot2_uint8_t *) (tag) + (((tag)->size + 7) & ~7)))
Expand Down Expand Up @@ -186,8 +187,8 @@ void map_multiboot_areas(void) {
paddr_t mbi_stop = mbi_start + multiboot2_hdr_size;

for (mfn_t mfn = paddr_to_mfn(mbi_start); mfn <= paddr_to_mfn(mbi_stop); mfn++) {
vmap_4k(mfn_to_virt(mfn), mfn, L1_PROT_RO);
kmap_4k(mfn, L1_PROT_RO);
vmap_kern_4k(mfn_to_virt(mfn), mfn, L1_PROT_RO);
vmap_kern_4k(mfn_to_virt_kern(mfn), mfn, L1_PROT_RO);
}
}

Expand Down
6 changes: 4 additions & 2 deletions arch/x86/ioapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <ktf.h>
#include <list.h>
#include <mm/slab.h>
#include <pagetable.h>
#include <string.h>

#define IOAPIC_SYSTEM_ISA_BUS_NAME "ISA"
Expand Down Expand Up @@ -217,8 +218,9 @@ ioapic_t *add_ioapic(uint8_t id, uint8_t version, bool enabled, uint64_t base_ad
ioapic->base_address = base_address;
ioapic->gsi_base = gsi_base;

ioapic->virt_address = vmap_4k(paddr_to_virt(ioapic->base_address),
paddr_to_mfn(ioapic->base_address), L1_PROT_NOCACHE);
ioapic->virt_address =
vmap_kern_4k(paddr_to_virt(ioapic->base_address),
paddr_to_mfn(ioapic->base_address), L1_PROT_NOCACHE);
BUG_ON(!ioapic->virt_address);

return ioapic;
Expand Down
117 changes: 99 additions & 18 deletions arch/x86/pagetables.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,31 +308,112 @@ static void *_vmap(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned int order,
return va;
}

void *vmap_kern(void *va, mfn_t mfn, unsigned int order,
static inline void *__vmap_1g(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned long l4_flags,
unsigned long l3_flags) {
return _vmap(cr3_ptr, va, mfn, PAGE_ORDER_1G, l4_flags, l3_flags | _PAGE_PSE,
PT_NO_FLAGS, PT_NO_FLAGS);
}

static inline void *__vmap_2m(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned long l4_flags,
unsigned long l3_flags, unsigned long l2_flags) {
return _vmap(cr3_ptr, va, mfn, PAGE_ORDER_2M, l4_flags, l3_flags,
l2_flags | _PAGE_PSE, PT_NO_FLAGS);
}

static inline void *__vmap_4k(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned long l4_flags,
unsigned long l3_flags, unsigned long l2_flags,
unsigned long l1_flags) {
return _vmap(cr3_ptr, va, mfn, PAGE_ORDER_4K, l4_flags, l3_flags, l2_flags, l1_flags);
}

static inline void *_vmap_1g(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned long l3_flags,
bool propagate_user) {
unsigned long l4_flags = L4_PROT;

if (propagate_user)
l4_flags |= l3_flags & _PAGE_USER;
return __vmap_1g(cr3_ptr, va, mfn, l4_flags, l3_flags);
}

static inline void *_vmap_2m(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned long l2_flags,
bool propagate_user) {
unsigned long l4_flags = L4_PROT;
unsigned long l3_flags = L3_PROT;

if (propagate_user) {
unsigned long user_bit = l2_flags & _PAGE_USER;
l4_flags |= user_bit;
l3_flags |= user_bit;
}
return __vmap_2m(cr3_ptr, va, mfn, l4_flags, l3_flags, l2_flags);
}

static inline void *_vmap_4k(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned long l1_flags,
bool propagate_user) {
unsigned long l4_flags = L4_PROT;
unsigned long l3_flags = L3_PROT;
unsigned long l2_flags = L2_PROT;

if (propagate_user) {
unsigned long user_bit = l1_flags & _PAGE_USER;
l4_flags |= user_bit;
l3_flags |= user_bit;
l2_flags |= user_bit;
}

return __vmap_4k(cr3_ptr, va, mfn, l4_flags, l3_flags, l2_flags, l1_flags);
}

void *vmap(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned int order,
#if defined(__x86_64__)
unsigned long l4_flags,
unsigned long l4_flags,
#endif
unsigned long l3_flags, unsigned long l2_flags, unsigned long l1_flags) {
unsigned long _va = _ul(va) & PAGE_ORDER_TO_MASK(order);

unsigned long l3_flags, unsigned long l2_flags, unsigned long l1_flags) {
dprintk("%s: va: 0x%p mfn: 0x%lx (order: %u)\n", __func__, va, mfn, order);

spin_lock(&vmap_lock);
va = _vmap(cr3_ptr, va, mfn, order, l4_flags, l3_flags, l2_flags, l1_flags);
spin_unlock(&vmap_lock);

return va;
}

void *vmap_1g(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned long l3_flags,
bool propagate_user) {
unsigned long _va = _ul(va) & PAGE_ORDER_TO_MASK(PAGE_ORDER_1G);

dprintk("%s: va: 0x%p mfn: 0x%lx\n", __func__, va, mfn);

spin_lock(&vmap_lock);
va = _vmap(&cr3, _ptr(_va), mfn, order, l4_flags, l3_flags, l2_flags, l1_flags);
va = _vmap_1g(cr3_ptr, _ptr(_va), mfn, l3_flags, propagate_user);
spin_unlock(&vmap_lock);

return va;
}

void *vmap_user(void *va, mfn_t mfn, unsigned int order,
#if defined(__x86_64__)
unsigned long l4_flags,
#endif
unsigned long l3_flags, unsigned long l2_flags, unsigned long l1_flags) {
unsigned long _va = _ul(va) & PAGE_ORDER_TO_MASK(order);
void *vmap_2m(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned long l2_flags,
bool propagate_user) {
unsigned long _va = _ul(va) & PAGE_ORDER_TO_MASK(PAGE_ORDER_2M);

dprintk("%s: va: 0x%p mfn: 0x%lx\n", __func__, va, mfn);

spin_lock(&vmap_lock);
va = _vmap_2m(cr3_ptr, _ptr(_va), mfn, l2_flags, propagate_user);
spin_unlock(&vmap_lock);

return va;
}

void *vmap_4k(cr3_t *cr3_ptr, void *va, mfn_t mfn, unsigned long l1_flags,
bool propagate_user) {
unsigned long _va = _ul(va) & PAGE_ORDER_TO_MASK(PAGE_ORDER_4K);

dprintk("%s: va: 0x%p mfn: 0x%lx\n", __func__, va, mfn);

dprintk("%s: va: 0x%p mfn: 0x%lx (order: %u)\n", __func__, va, mfn, order);
spin_lock(&vmap_lock);
va = _vmap(&user_cr3, _ptr(_va), mfn, order, l4_flags, l3_flags, l2_flags, l1_flags);
va = _vmap_4k(cr3_ptr, _ptr(_va), mfn, l1_flags, propagate_user);
spin_unlock(&vmap_lock);

return va;
}

Expand All @@ -349,7 +430,7 @@ static void map_tmp_mapping_entry(void) {
pte_t *entry = l1_table_entry(mfn_to_virt(l1e->mfn), _tmp_mapping);

/* Map _tmp_mapping_entry PTE of new page tables */
kmap_4k(l1e->mfn, L1_PROT);
vmap_kern_4k(mfn_to_virt_kern(l1e->mfn), l1e->mfn, L1_PROT);

/* Point _tmp_mapping_entry at new page tables location */
_tmp_mapping_entry = paddr_to_virt_kern(_paddr(entry));
Expand Down Expand Up @@ -789,17 +870,17 @@ void init_pagetables(void) {
switch (r->base) {
case VIRT_IDENT_BASE:
for (mfn_t mfn = virt_to_mfn(r->start); mfn < virt_to_mfn(r->end); mfn++)
vmap_4k(mfn_to_virt(mfn), mfn, r->flags);
vmap_kern_4k(mfn_to_virt(mfn), mfn, r->flags);
break;
case VIRT_KERNEL_BASE:
for (mfn_t mfn = virt_to_mfn(r->start); mfn < virt_to_mfn(r->end); mfn++)
kmap_4k(mfn, r->flags);
vmap_kern_4k(mfn_to_virt_kern(mfn), mfn, r->flags);
break;
case VIRT_USER_BASE:
for (mfn_t mfn = virt_to_mfn(r->start); mfn < virt_to_mfn(r->end); mfn++) {
void *va = mfn_to_virt_user(mfn);

vmap_4k(va, mfn, r->flags);
vmap_kern_4k(va, mfn, r->flags);
vmap_user_4k(va, mfn, r->flags);
}
break;
Expand Down
11 changes: 6 additions & 5 deletions common/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,16 +136,17 @@ void zap_boot_mappings(void) {
}

static void __text_init map_bios_area(void) {
vmap_4k(paddr_to_virt(BDA_ADDR_START), paddr_to_mfn(BDA_ADDR_START), L1_PROT_RO);
kmap_4k(paddr_to_mfn(BDA_ADDR_START), L1_PROT_RO);
vmap_kern_4k(paddr_to_virt(BDA_ADDR_START), paddr_to_mfn(BDA_ADDR_START), L1_PROT_RO);
vmap_kern_4k(paddr_to_virt_kern(BDA_ADDR_START), paddr_to_mfn(BDA_ADDR_START),
L1_PROT_RO);

uint32_t ebda_addr = get_bios_ebda_addr();
vmap_4k(paddr_to_virt(ebda_addr), paddr_to_mfn(ebda_addr), L1_PROT_RO);
kmap_4k(paddr_to_mfn(ebda_addr), L1_PROT_RO);
vmap_kern_4k(paddr_to_virt(ebda_addr), paddr_to_mfn(ebda_addr), L1_PROT_RO);
vmap_kern_4k(paddr_to_virt_kern(ebda_addr), paddr_to_mfn(ebda_addr), L1_PROT_RO);

for (mfn_t bios_mfn = paddr_to_mfn(BIOS_ACPI_ROM_START);
bios_mfn < paddr_to_mfn(BIOS_ACPI_ROM_STOP); bios_mfn++)
kmap_4k(bios_mfn, L1_PROT_RO);
vmap_kern_4k(mfn_to_virt_kern(bios_mfn), bios_mfn, L1_PROT_RO);
}

static void display_cpu_info(void) {
Expand Down
3 changes: 2 additions & 1 deletion drivers/acpi/acpica/osl.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <cpu.h>
#include <ktf.h>
#include <mm/slab.h>
#include <pagetable.h>
#include <pci_cfg.h>
#include <percpu.h>
#include <sched.h>
Expand Down Expand Up @@ -306,7 +307,7 @@ void *AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS PhysicalAddress, ACPI_SIZE Length) {
void *_va;

if (!frame) {
_va = vmap_4k(mfn_to_virt_map(mfn), mfn, L1_PROT);
_va = vmap_kern_4k(mfn_to_virt_map(mfn), mfn, L1_PROT);
if (!_va) {
spin_unlock(&map_lock);
return NULL;
Expand Down
6 changes: 3 additions & 3 deletions drivers/fb/fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include <drivers/logo.h>
#include <ktf.h>
#include <multiboot2.h>
#include <page.h>
#include <pagetable.h>
#include <string.h>

extern uint64_t fonts[];
Expand Down Expand Up @@ -56,8 +56,8 @@ static void (*put_pixel)(uint32_t x, uint32_t y, uint32_t color);
static void map_fb_area(paddr_t start, size_t size) {
for (mfn_t video_mfn = paddr_to_mfn(start); video_mfn < paddr_to_mfn(start + size);
video_mfn++) {
vmap_4k(mfn_to_virt(video_mfn), video_mfn, L1_PROT_NOCACHE);
kmap_4k(video_mfn, L1_PROT_NOCACHE);
vmap_kern_4k(mfn_to_virt(video_mfn), video_mfn, L1_PROT_NOCACHE);
vmap_kern_4k(mfn_to_virt_kern(video_mfn), video_mfn, L1_PROT_NOCACHE);
}
}

Expand Down
3 changes: 2 additions & 1 deletion drivers/hpet.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <acpi_ktf.h>
#include <drivers/hpet.h>
#include <ioapic.h>
#include <pagetable.h>

bool init_hpet(const cpu_t *cpu) {
#ifndef KTF_ACPICA
Expand Down Expand Up @@ -59,7 +60,7 @@ bool init_hpet(const cpu_t *cpu) {
#endif

hpet_base_mfn = paddr_to_mfn(address);
vmap_4k(_ptr(address), hpet_base_mfn, L1_PROT_NOCACHE);
vmap_kern_4k(_ptr(address), hpet_base_mfn, L1_PROT_NOCACHE);
config = (acpi_hpet_timer_t *) (address + HPET_OFFSET_TIMER_0_CONFIG_CAP_REG);
general = (acpi_hpet_general_t *) (address + HPET_OFFSET_GENERAL_CAP_REG);
main_counter = (uint64_t *) (address + HPET_OFFSET_GENERAL_MAIN_COUNTER_REG);
Expand Down
6 changes: 3 additions & 3 deletions drivers/vga.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*/
#include <drivers/vga.h>
#include <ktf.h>
#include <page.h>
#include <pagetable.h>
#include <string.h>

#define MAX_ROWS VGA_ROWS
Expand Down Expand Up @@ -83,7 +83,7 @@ void vga_write(void *vga_memory, const char *buf, size_t len, vga_color_t color)
void map_vga_area(void) {
for (mfn_t vga_mfn = paddr_to_mfn(VGA_START_ADDR);
vga_mfn < paddr_to_mfn(VGA_END_ADDR); vga_mfn++) {
vmap_4k(mfn_to_virt(vga_mfn), vga_mfn, L1_PROT_NOCACHE);
kmap_4k(vga_mfn, L1_PROT_NOCACHE);
vmap_kern_4k(mfn_to_virt(vga_mfn), vga_mfn, L1_PROT_NOCACHE);
vmap_kern_4k(mfn_to_virt_kern(vga_mfn), vga_mfn, L1_PROT_NOCACHE);
}
}
77 changes: 0 additions & 77 deletions include/arch/x86/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,22 +175,6 @@ typedef unsigned long mfn_t;

/* External declarations */

extern void *vmap_kern(void *va, mfn_t mfn, unsigned int order,
#if defined(__x86_64__)
unsigned long l4_flags,
#endif
unsigned long l3_flags, unsigned long l2_flags,
unsigned long l1_flags);

extern void *vmap_user(void *va, mfn_t mfn, unsigned int order,
#if defined(__x86_64__)
unsigned long l4_flags,
#endif
unsigned long l3_flags, unsigned long l2_flags,
unsigned long l1_flags);

extern int vunmap_kern(void *va, mfn_t *mfn, unsigned int *order);
extern int vunmap_user(void *va, mfn_t *mfn, unsigned int *order);
extern void pat_set_type(pat_field_t field, pat_memory_type_t type);
extern pat_memory_type_t pat_get_type(pat_field_t field);

Expand Down Expand Up @@ -257,67 +241,6 @@ static inline mfn_t virt_to_mfn(const void *va) {
return paddr_to_mfn(virt_to_paddr(va));
}

static inline void *kmap(mfn_t mfn, unsigned int order,
#if defined(__x86_64__)
unsigned long l4_flags,
#endif
unsigned long l3_flags, unsigned long l2_flags,
unsigned long l1_flags) {
return vmap_kern(mfn_to_virt_kern(mfn), mfn, order,
#if defined(__x86_64__)
l4_flags,
#endif
l3_flags, l2_flags, l1_flags);
}

static inline void *vmap_1g(void *va, mfn_t mfn, unsigned long l3_flags) {
return vmap_kern(va, mfn, PAGE_ORDER_1G, L4_PROT, l3_flags | _PAGE_PSE, PT_NO_FLAGS,
PT_NO_FLAGS);
}

static inline void *vmap_2m(void *va, mfn_t mfn, unsigned long l2_flags) {
return vmap_kern(va, mfn, PAGE_ORDER_2M, L4_PROT, L3_PROT, l2_flags | _PAGE_PSE,
PT_NO_FLAGS);
}

static inline void *vmap_4k(void *va, mfn_t mfn, unsigned long l1_flags) {
return vmap_kern(va, mfn, PAGE_ORDER_4K, L4_PROT, L3_PROT, L2_PROT, l1_flags);
}

static inline void *kmap_1g(mfn_t mfn, unsigned long l3_flags) {
return kmap(mfn, PAGE_ORDER_1G, L4_PROT, l3_flags | _PAGE_PSE, PT_NO_FLAGS,
PT_NO_FLAGS);
}

static inline void *kmap_2m(mfn_t mfn, unsigned long l2_flags) {
return kmap(mfn, PAGE_ORDER_2M, L4_PROT, L3_PROT, l2_flags | _PAGE_PSE, PT_NO_FLAGS);
}

static inline void *kmap_4k(mfn_t mfn, unsigned long l1_flags) {
return kmap(mfn, PAGE_ORDER_4K, L4_PROT, L3_PROT, L2_PROT, l1_flags);
}

static inline void *vmap_user_1g(void *va, mfn_t mfn, unsigned long l3_flags) {
unsigned long user = l3_flags & _PAGE_USER;

return vmap_user(va, mfn, PAGE_ORDER_1G, L4_PROT | user,
l3_flags | (user | _PAGE_PSE), PT_NO_FLAGS, PT_NO_FLAGS);
}

static inline void *vmap_user_2m(void *va, mfn_t mfn, unsigned long l2_flags) {
unsigned long user = l2_flags & _PAGE_USER;

return vmap_user(va, mfn, PAGE_ORDER_2M, L4_PROT | user, L3_PROT | user,
l2_flags | (user | _PAGE_PSE), PT_NO_FLAGS);
}

static inline void *vmap_user_4k(void *va, mfn_t mfn, unsigned long l1_flags) {
unsigned long user = l1_flags & _PAGE_USER;

return vmap_user(va, mfn, PAGE_ORDER_4K, L4_PROT | user, L3_PROT | user,
L2_PROT | user, l1_flags);
}

#endif /* __ASSEMBLY__ */

#endif /* KTF_PAGE_H */
Loading

0 comments on commit 4b429f3

Please sign in to comment.