[arch][m68k] add arch_mmu_query so the kernel boots completely

Side effect of editing: reformat all of the code in
platform/qemu-virt-m68k
This commit is contained in:
Travis Geiselbrecht
2025-09-07 18:49:58 -07:00
parent 6c7e6a1796
commit bb5db64b4c
8 changed files with 145 additions and 90 deletions

View File

@@ -9,6 +9,8 @@
#if M68K_MMU
#include <arch/mmu.h>
#include <arch/spinlock.h>
#include <assert.h>
#include <kernel/vm.h>
#include <lk/err.h>
@@ -16,9 +18,9 @@
#include <stdint.h>
#include <stdlib.h>
#define LOCAL_TRACE 1
#define LOCAL_TRACE 0
// initial mappings set up in start.S using the DTTR and ITTR registers
// initial mappings set up in start.S
struct mmu_initial_mapping mmu_initial_mappings[] = {
// all of memory, mapped in start.S
{
@@ -377,14 +379,6 @@ void m68k_mmu_init(void) {
LTRACE_EXIT;
}
// arch mmu routines
#endif // M68K_MMU
#if ARCH_HAS_MMU
#include <arch/mmu.h>
// Default stub implementations for arch_mmu routines
bool arch_mmu_supports_nx_mappings(void) {
@@ -416,7 +410,47 @@ int arch_mmu_unmap(arch_aspace_t *aspace, vaddr_t vaddr, uint count) {
}
status_t arch_mmu_query(arch_aspace_t *aspace, vaddr_t vaddr, paddr_t *paddr, uint *flags) {
return ERR_NOT_SUPPORTED;
// Disable interrupts around the ptest instruction in case we get preempted
spin_lock_saved_state_t state;
arch_interrupt_save(&state, 0);
// Use the PTEST instruction to probe the translation
uint32_t mmusr;
asm volatile(
"ptestr (%1)\n"
"movec %%mmusr, %0"
: "=r"(mmusr) : "a"(vaddr) : "memory");
arch_interrupt_restore(state, 0);
LTRACEF("vaddr %#x, mmusr %#x\n", (uint32_t)vaddr, mmusr);
if ((mmusr & 0x1) == 0) {
return ERR_NOT_FOUND;
}
// extract the physical address from the mmusr
if (paddr) {
*paddr = (mmusr & 0xfffff000) | (vaddr & 0xfff);
}
if (flags) {
*flags = 0;
*flags |= (mmusr & (1 << 2)) ? ARCH_MMU_FLAG_PERM_RO : 0;
*flags |= (mmusr & (1 << 7)) ? 0 : ARCH_MMU_FLAG_PERM_USER;
uint32_t cm = mmusr & (3 << 5);
switch (cm) {
case 0:
case 1:
*flags |= ARCH_MMU_FLAG_CACHED;
break;
case 2:
*flags |= ARCH_MMU_FLAG_UNCACHED_DEVICE;
break;
case 3:
*flags |= ARCH_MMU_FLAG_UNCACHED;
break;
}
}
return NO_ERROR;
}
vaddr_t arch_mmu_pick_spot(arch_aspace_t *aspace,
@@ -430,4 +464,4 @@ void arch_mmu_context_switch(arch_aspace_t *aspace) {
// no-op
}
#endif // ARCH_HAS_MMU
#endif // M68K_MMU

View File

@@ -8,8 +8,8 @@
#include "bootinfo.h"
#include <lk/compiler.h>
#include <lk/trace.h>
#include <lk/debug.h>
#include <lk/trace.h>
#include <stdio.h>
#define LOCAL_TRACE 0
@@ -18,22 +18,38 @@ extern uint8_t __bss_end;
static const char *bootinfo_tag_to_string(enum BOOTINFO_TAGS tag) {
switch (tag) {
case BOOTINFO_TAG_END: return "END";
case BOOTINFO_TAG_MACHTYPE: return "MACHTYPE";
case BOOTINFO_TAG_CPUTYPE: return "CPUTYPE";
case BOOTINFO_TAG_FPUTYPE: return "FPUTYPE";
case BOOTINFO_TAG_MMUTYPE: return "MMUTYPE";
case BOOTINFO_TAG_MEMCHUNK: return "MEMCHUNK";
case BOOTINFO_TAG_RAMDISK: return "RAMDISK";
case BOOTINFO_TAG_COMMAND_LINE: return "COMMAND_LINE";
case BOOTINFO_TAG_RNG_SEED: return "RNG_SEED";
case BOOTINFO_TAG_VIRT_QEMU_VERSION: return "VIRT_QEMU_VERSION";
case BOOTINFO_TAG_VIRT_GF_PIC_BASE: return "VIRT_GF_PIC_BASE";
case BOOTINFO_TAG_VIRT_GF_RTC_BASE: return "VIRT_GF_RTC_BASE";
case BOOTINFO_TAG_VIRT_GF_TTY_BASE: return "VIRT_GF_TTY_BASE";
case BOOTINFO_TAG_VIRT_VIRTIO_BASE: return "VIRT_VIRTIO_BASE";
case BOOTINFO_TAG_VIRT_CTRL_BASE: return "VIRT_CTRL_BASE";
default: return "UNKNOWN";
case BOOTINFO_TAG_END:
return "END";
case BOOTINFO_TAG_MACHTYPE:
return "MACHTYPE";
case BOOTINFO_TAG_CPUTYPE:
return "CPUTYPE";
case BOOTINFO_TAG_FPUTYPE:
return "FPUTYPE";
case BOOTINFO_TAG_MMUTYPE:
return "MMUTYPE";
case BOOTINFO_TAG_MEMCHUNK:
return "MEMCHUNK";
case BOOTINFO_TAG_RAMDISK:
return "RAMDISK";
case BOOTINFO_TAG_COMMAND_LINE:
return "COMMAND_LINE";
case BOOTINFO_TAG_RNG_SEED:
return "RNG_SEED";
case BOOTINFO_TAG_VIRT_QEMU_VERSION:
return "VIRT_QEMU_VERSION";
case BOOTINFO_TAG_VIRT_GF_PIC_BASE:
return "VIRT_GF_PIC_BASE";
case BOOTINFO_TAG_VIRT_GF_RTC_BASE:
return "VIRT_GF_RTC_BASE";
case BOOTINFO_TAG_VIRT_GF_TTY_BASE:
return "VIRT_GF_TTY_BASE";
case BOOTINFO_TAG_VIRT_VIRTIO_BASE:
return "VIRT_VIRTIO_BASE";
case BOOTINFO_TAG_VIRT_CTRL_BASE:
return "VIRT_CTRL_BASE";
default:
return "UNKNOWN";
}
}
@@ -88,4 +104,3 @@ const void *bootinfo_find_record(uint16_t id, uint16_t *size_out) {
ptr += item->size;
}
}

View File

@@ -7,34 +7,32 @@
*/
#include "platform_p.h"
#include <assert.h>
#include <inttypes.h>
#include <lk/err.h>
#include <lk/debug.h>
#include <lk/reg.h>
#include <lk/trace.h>
#include <kernel/debug.h>
#include <kernel/thread.h>
#include <platform/interrupts.h>
#include <platform/virt.h>
#include <platform/timer.h>
#include <lk/debug.h>
#include <lk/err.h>
#include <lk/reg.h>
#include <lk/trace.h>
#include <platform.h>
#include <platform/interrupts.h>
#include <platform/timer.h>
#include <platform/virt.h>
#define LOCAL_TRACE 0
// implementation of RTC at
// https://github.com/qemu/qemu/blob/master/hw/rtc/goldfish_rtc.c
volatile uint32_t * const goldfish_rtc_base = (void *)VIRT_GF_RTC_MMIO_BASE;
volatile uint32_t *const goldfish_rtc_base = (void *)VIRT_GF_RTC_MMIO_BASE;
// registers
enum {
RTC_TIME_LOW = 0x00,
RTC_TIME_HIGH = 0x04,
RTC_ALARM_LOW = 0x08,
RTC_ALARM_HIGH = 0x0c,
RTC_IRQ_ENABLED = 0x10,
RTC_CLEAR_ALARM = 0x14,
RTC_ALARM_STATUS = 0x18,
RTC_TIME_LOW = 0x00,
RTC_TIME_HIGH = 0x04,
RTC_ALARM_LOW = 0x08,
RTC_ALARM_HIGH = 0x0c,
RTC_IRQ_ENABLED = 0x10,
RTC_CLEAR_ALARM = 0x14,
RTC_ALARM_STATUS = 0x18,
RTC_CLEAR_INTERRUPT = 0x1c,
};
@@ -105,7 +103,7 @@ lk_time_t current_time(void) {
return (lk_time_t)(t / 1000000ULL); // ns -> ms
}
status_t platform_set_oneshot_timer (platform_timer_callback callback, void *arg, lk_time_t interval) {
status_t platform_set_oneshot_timer(platform_timer_callback callback, void *arg, lk_time_t interval) {
LTRACEF("callback %p, arg %p, interval %u\n", callback, arg, interval);
t_callback = callback;
@@ -126,5 +124,3 @@ void platform_stop_timer(void) {
write_reg(RTC_CLEAR_ALARM, 1);
write_reg(RTC_CLEAR_INTERRUPT, 1);
}

View File

@@ -5,40 +5,44 @@
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT
*/
#include <kernel/thread.h>
#include <lib/cbuf.h>
#include <lk/reg.h>
#include <lk/trace.h>
#include <lib/cbuf.h>
#include <kernel/thread.h>
#include <platform.h>
#include <platform/interrupts.h>
#include <platform/debug.h>
#include <platform/interrupts.h>
#include <platform/virt.h>
#include <sys/types.h>
#if WITH_KERNEL_VM
#include <kernel/vm.h>
#endif
#include "platform_p.h"
// goldfish tty
// from https://github.com/qemu/qemu/blob/master/hw/char/goldfish_tty.c
volatile uint32_t * const goldfish_tty_base = (void *)VIRT_GF_TTY_MMIO_BASE;
volatile uint32_t *const goldfish_tty_base = (void *)VIRT_GF_TTY_MMIO_BASE;
// registers
enum {
REG_PUT_CHAR = 0x00,
REG_BYTES_READY = 0x04,
REG_CMD = 0x08,
REG_DATA_PTR = 0x10,
REG_DATA_LEN = 0x14,
REG_PUT_CHAR = 0x00,
REG_BYTES_READY = 0x04,
REG_CMD = 0x08,
REG_DATA_PTR = 0x10,
REG_DATA_LEN = 0x14,
REG_DATA_PTR_HIGH = 0x18,
REG_VERSION = 0x20,
REG_VERSION = 0x20,
};
// commands
enum {
CMD_INT_DISABLE = 0x00,
CMD_INT_ENABLE = 0x01,
CMD_WRITE_BUFFER = 0x02,
CMD_READ_BUFFER = 0x03,
CMD_INT_DISABLE = 0x00,
CMD_INT_ENABLE = 0x01,
CMD_WRITE_BUFFER = 0x02,
CMD_READ_BUFFER = 0x03,
};
#define RXBUF_SIZE 128
@@ -59,7 +63,8 @@ static enum handler_return uart_irq_handler(void *arg) {
bool resched = false;
// use a DMA read of one byte if a byte is ready
if (read_reg(REG_BYTES_READY) > 0) {
uint32_t ready = read_reg(REG_BYTES_READY);
if (ready > 0) {
write_reg(REG_CMD, CMD_READ_BUFFER);
char c = transfer_buf[0];
cbuf_write_char(&uart_rx_buf, c, false);
@@ -74,7 +79,13 @@ void goldfish_tty_early_init(void) {
write_reg(REG_CMD, CMD_INT_DISABLE);
// set up the transfer buffer for receives
write_reg(REG_DATA_PTR, (uint32_t)transfer_buf);
uint32_t buf_addr;
#if WITH_KERNEL_VM
buf_addr = (uint32_t)vaddr_to_paddr(transfer_buf);
#else
buf_addr = (uint32_t)transfer_buf;
#endif
write_reg(REG_DATA_PTR, buf_addr);
write_reg(REG_DATA_PTR_HIGH, 0);
write_reg(REG_DATA_LEN, sizeof(transfer_buf));
}
@@ -103,8 +114,9 @@ int uart_getc(char *c, bool wait) {
}
void platform_dputc(char c) {
if (c == '\n')
if (c == '\n') {
platform_dputc('\r');
}
uart_putc(c);
}

View File

@@ -30,18 +30,18 @@
* CPU IRQ #7 -> NMI
*/
#define VIRT_GF_PIC_MMIO_BASE 0xff000000 /* MMIO: 0xff000000 - 0xff005fff */
#define VIRT_GF_PIC_IRQ_BASE 1 /* IRQ: #1 -> #6 */
#define VIRT_GF_PIC_MMIO_BASE 0xff000000 /* MMIO: 0xff000000 - 0xff005fff */
#define VIRT_GF_PIC_IRQ_BASE 1 /* IRQ: #1 -> #6 */
#define VIRT_GF_PIC_NB 6
#define NUM_IRQS (VIRT_GF_PIC_NB * 32) // PIC 1 - 6
#define NUM_IRQS (VIRT_GF_PIC_NB * 32) // PIC 1 - 6
/* maps (pic + irq) base one to a linear number zero based */
#define PIC_IRQ(pic, irq) (((pic) - 1) * 32 + ((irq) - 1))
#define PIC_IRQ(pic, irq) (((pic) - 1) * 32 + ((irq) - 1))
/* 2 goldfish-rtc (and timer) */
#define VIRT_GF_RTC_MMIO_BASE 0xff006000 /* MMIO: 0xff006000 - 0xff007fff */
#define VIRT_GF_RTC_IRQ_BASE PIC_IRQ(6, 1) /* PIC: #6, IRQ: #1 */
#define VIRT_GF_RTC_MMIO_BASE 0xff006000 /* MMIO: 0xff006000 - 0xff007fff */
#define VIRT_GF_RTC_IRQ_BASE PIC_IRQ(6, 1) /* PIC: #6, IRQ: #1 */
#define VIRT_GF_RTC_NB 2
/* 1 goldfish-tty */
@@ -50,7 +50,7 @@
/* 1 virt-ctrl */
#define VIRT_CTRL_MMIO_BASE 0xff009000 /* MMIO: 0xff009000 - 0xff009fff */
#define VIRT_CTRL_IRQ_BASE PIC_IRQ(1, 1) /* PIC: #1, IRQ: #1 */
#define VIRT_CTRL_IRQ_BASE PIC_IRQ(1, 1) /* PIC: #1, IRQ: #1 */
/*
* virtio-mmio size is 0x200 bytes
@@ -58,7 +58,7 @@
* we can attach 32 virtio devices / goldfish-pic
* -> we can manage 32 * 4 = 128 virtio devices
*/
#define VIRT_VIRTIO_MMIO_BASE 0xff010000 /* MMIO: 0xff010000 - 0xff01ffff */
#define VIRT_VIRTIO_IRQ_BASE PIC_IRQ(2, 1) /* PIC: 2, 3, 4, 5, IRQ: ALL */
#define VIRT_VIRTIO_MMIO_BASE 0xff010000 /* MMIO: 0xff010000 - 0xff01ffff */
#define VIRT_VIRTIO_IRQ_BASE PIC_IRQ(2, 1) /* PIC: 2, 3, 4, 5, IRQ: ALL */
#define NUM_VIRT_VIRTIO 128

View File

@@ -8,13 +8,13 @@
#include "platform_p.h"
#include <assert.h>
#include <lk/bits.h>
#include <lk/err.h>
#include <lk/debug.h>
#include <lk/reg.h>
#include <lk/trace.h>
#include <kernel/debug.h>
#include <kernel/thread.h>
#include <lk/bits.h>
#include <lk/debug.h>
#include <lk/err.h>
#include <lk/reg.h>
#include <lk/trace.h>
#include <platform/interrupts.h>
#include <platform/virt.h>
@@ -24,14 +24,14 @@
// https://github.com/qemu/qemu/blob/master/hw/intc/goldfish_pic.c
enum {
REG_STATUS = 0x00,
REG_IRQ_PENDING = 0x04,
REG_STATUS = 0x00,
REG_IRQ_PENDING = 0x04,
REG_IRQ_DISABLE_ALL = 0x08,
REG_DISABLE = 0x0c,
REG_ENABLE = 0x10,
REG_DISABLE = 0x0c,
REG_ENABLE = 0x10,
};
volatile uint32_t * const goldfish_pic_base = (void *)VIRT_GF_PIC_MMIO_BASE;
volatile uint32_t *const goldfish_pic_base = (void *)VIRT_GF_PIC_MMIO_BASE;
static struct int_handlers {
int_handler handler;
@@ -128,4 +128,3 @@ enum handler_return m68k_platform_irq(uint8_t m68k_irq) {
return ret;
}

View File

@@ -98,7 +98,8 @@ void platform_init(void) {
goldfish_rtc_init();
#if M68K_MMU == 68040
// TODO: create a VM reservation for peripheral space thats using DTTR1
// create a VM reservation for peripheral space thats using DTTR1
vmm_reserve_space(vmm_get_kernel_aspace(), "periph", 0x1000000, 0xff000000);
#endif
/* detect any virtio devices */

View File

@@ -7,8 +7,6 @@
*/
#pragma once
#include <stdbool.h>
void uart_init(void);
void pic_early_init(void);