Skip to content

ARM: add support for Azure instances #2041

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 13, 2024
1 change: 1 addition & 0 deletions platform/pc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ SRCS-kernel.elf= \
$(SRCDIR)/x86_64/crt0.s \
$(SRCDIR)/x86_64/elf64.c \
$(SRCDIR)/x86_64/hpet.c \
$(SRCDIR)/x86_64/hyperv.c \
$(SRCDIR)/x86_64/init.s \
$(SRCDIR)/x86_64/interrupt.c \
$(SRCDIR)/x86_64/kernel_machine.c \
Expand Down
14 changes: 14 additions & 0 deletions platform/virt/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ SRCS-kernel.elf= \
$(SRCDIR)/aarch64/crt0.S \
$(SRCDIR)/aarch64/elf64.c \
$(SRCDIR)/aarch64/gic.c \
$(SRCDIR)/aarch64/hyperv.c \
$(SRCDIR)/aarch64/interrupt.c \
$(SRCDIR)/aarch64/kernel_machine.c \
$(SRCDIR)/aarch64/page.c \
Expand All @@ -30,6 +31,7 @@ SRCS-kernel.elf= \
$(SRCDIR)/devicetree/devicetree.c \
$(SRCDIR)/drivers/acpi.c \
$(SRCDIR)/drivers/console.c \
$(SRCDIR)/drivers/dmi.c \
$(SRCDIR)/drivers/gve.c \
$(SRCDIR)/drivers/netconsole.c \
$(SRCDIR)/drivers/ns16550.c \
Expand All @@ -38,6 +40,17 @@ SRCS-kernel.elf= \
$(SRCDIR)/gdb/gdbtcp.c \
$(SRCDIR)/gdb/gdbutil.c \
$(SRCDIR)/http/http.c \
$(SRCDIR)/hyperv/netvsc/hv_net_vsc.c \
$(SRCDIR)/hyperv/netvsc/hv_rndis_filter.c \
$(SRCDIR)/hyperv/netvsc/netvsc.c \
$(SRCDIR)/hyperv/storvsc/storvsc.c \
$(SRCDIR)/hyperv/utilities/vmbus_ic.c \
$(SRCDIR)/hyperv/utilities/vmbus_shutdown.c \
$(SRCDIR)/hyperv/vmbus/hyperv.c \
$(SRCDIR)/hyperv/vmbus/vmbus.c \
$(SRCDIR)/hyperv/vmbus/vmbus_br.c \
$(SRCDIR)/hyperv/vmbus/vmbus_chan.c \
$(SRCDIR)/hyperv/vmbus/vmbus_xact.c \
$(SRCDIR)/kernel/elf.c \
$(SRCDIR)/kernel/clock.c \
$(SRCDIR)/kernel/flush.c \
Expand Down Expand Up @@ -152,6 +165,7 @@ INCLUDES=\
-I$(SRCDIR)/net \
-I$(SRCDIR)/runtime \
-I$(SRCDIR)/fs \
-I$(SRCDIR)/hyperv/include \
-I$(SRCDIR)/unix \
-I$(SRCDIR)/unix_process \
-I$(SRCDIR)/xen/public \
Expand Down
1 change: 1 addition & 0 deletions platform/virt/kernel_platform.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#define PHYSMEM_BASE 0x40000000
#define PHYSMEM_BASE_MASK 0x3fffffff
#define INIT_PAGEMEM 0x40200000
#define INIT_IDENTITY_SIZE 0x00600000

Expand Down
6 changes: 5 additions & 1 deletion platform/virt/pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ BSS_RO_AFTER_INIT static u64 pcie_ecam_base;
u32 pci_cfgread(pci_dev dev, int reg, int bytes)
{
u32 data = -1;
if (!pcie_ecam_base)
return data;
u64 base = pcie_ecam_base
+ (dev->bus << 20) + (dev->slot << 15) + (dev->function << 12) + reg;
pci_plat_debug("%s: dev %p, bus %d, reg 0x%02x, bytes %d, base 0x%lx: ", func_ss,
Expand All @@ -47,6 +49,8 @@ u32 pci_cfgread(pci_dev dev, int reg, int bytes)

void pci_cfgwrite(pci_dev dev, int reg, int bytes, u32 source)
{
if (!pcie_ecam_base)
return;
u64 base = pcie_ecam_base
+ (dev->bus << 20) + (dev->slot << 15) + (dev->function << 12) + reg;
pci_plat_debug("%s: dev %p, bus %d, reg 0x%02x, bytes %d, base 0x%lx= 0x%x\n",
Expand Down Expand Up @@ -115,7 +119,7 @@ closure_func_basic(mcfg_handler, boolean, pci_mcfg_handler,
u64 addr, u16 segment, u8 bus_start, u8 bus_end)
{
if ((segment == 0) && (bus_start == 0)) {
pcie_ecam_base = DEVICE_BASE + addr;
pcie_ecam_base = DEVICE_BASE + (addr & (DEV_MAP_SIZE - 1));
return true;
}
return false;
Expand Down
148 changes: 131 additions & 17 deletions platform/virt/service.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,19 @@
#include <boot/uefi.h>
#include <drivers/acpi.h>
#include <drivers/console.h>
#include <drivers/dmi.h>
#include <drivers/gve.h>
#include <drivers/ns16550.h>
#include <drivers/nvme.h>
#include <management.h>
#include <virtio/virtio.h>
#include <devicetree.h>
#include <hyperv_platform.h>
#include "serial.h"

#define SERIAL_16550_COMPATIBLE 0x00
#define SERIAL_16550_SUBSET 0x01
#define SERIAL_ARM_PL011 0x03
#define SERIAL_16550_WITH_GAS 0x12

//#define INIT_DEBUG
Expand Down Expand Up @@ -165,13 +168,14 @@ id_heap init_physical_id_heap(heap h)
u64 map_base = u64_from_pointer(boot_params.mem_map.map);
u64 map_size = pad((map_base & PAGEMASK) + boot_params.mem_map.map_size, PAGESIZE);
map_base &= ~PAGEMASK;
map(map_base, map_base, map_size, pageflags_memory());
/* map_base has been identity-mapped in ueft_rt_init_virt() */
u64 mem_size = 0;
uefi_mem_map_iterate(&boot_params.mem_map, stack_closure(get_mem_size, &mem_size));
init_debug("\nmem size ");
init_debug_u64(mem_size);
u64 bootstrap_size = init_bootstrap_heap(mem_size);
range reserved = irange(DEVICETREE_BLOB_BASE, KERNEL_PHYS + kernel_size);
range reserved = irange(DEVICETREE_BLOB_BASE + kernel_phys_offset,
KERNEL_PHYS + kernel_size + kernel_phys_offset);
u64 base = 0;
uefi_mem_map_iterate(&boot_params.mem_map,
stack_closure(get_bootstrap_base, reserved, bootstrap_size, &base));
Expand Down Expand Up @@ -239,6 +243,82 @@ void vm_reset(void)
u64 total_processors = 1;
BSS_RO_AFTER_INIT u64 present_processors;

static void ueft_rt_init_virt(void)
{
u64 virt_addr = KERNEL_BASE;
uefi_mem_map mem_map = &boot_params.mem_map;
u64 map_base = u64_from_pointer(mem_map->map);
u64 map_size = pad((map_base & PAGEMASK) + mem_map->map_size, PAGESIZE);
map_base &= ~PAGEMASK;
pageflags flags = pageflags_writable(pageflags_memory());
map(map_base, map_base, map_size, flags); /* will be unmapped in init_physical_id_heap() */
int num_desc = mem_map->map_size / mem_map->desc_size;
u64 rt_svc_offset = 0;
for (int i = 0; i < num_desc; i++) {
efi_memory_desc d = mem_map->map + i * mem_map->desc_size;
if (d->type == efi_runtime_services_data) {
u64 phys_addr = d->physical_start;
u64 mem_len = d->number_of_pages * PAGESIZE;
map(phys_addr, phys_addr, mem_len, flags);
virt_addr -= mem_len;
init_debug("UEFI runtime services data at ");
init_debug_u64(phys_addr);
init_debug(", length ");
init_debug_u64(mem_len);
init_debug(", mapping at ");
init_debug_u64(virt_addr);
init_debug("\n");
map(virt_addr, phys_addr, mem_len, flags);
d->virtual_start = pointer_from_u64(virt_addr);
if (point_in_range(irangel(phys_addr, mem_len),
u64_from_pointer(boot_params.efi_rt_svc)))
rt_svc_offset = virt_addr - phys_addr;
}
}
flags = pageflags_exec(pageflags_memory());

/* set_virtual_address_map() needs write access to code memory */
pageflags temp_flags = pageflags_writable(flags);

for (int i = 0; i < num_desc; i++) {
efi_memory_desc d = mem_map->map + i * mem_map->desc_size;
if ((d->attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) {
u64 phys_addr = d->physical_start;
u32 mem_type = d->type;
if (mem_type == efi_memory_mapped_io) { /* already mapped */
d->virtual_start = pointer_from_u64(DEVICE_BASE + (phys_addr & (DEV_MAP_SIZE - 1)));
continue;
} else if (mem_type == efi_runtime_services_code) {
u64 mem_len = d->number_of_pages * PAGESIZE;
map(phys_addr, phys_addr, mem_len, temp_flags);
virt_addr -= mem_len;
init_debug("UEFI runtime services code at ");
init_debug_u64(phys_addr);
init_debug(", length ");
init_debug_u64(mem_len);
init_debug(", mapping at ");
init_debug_u64(virt_addr);
init_debug("\n");
d->virtual_start = pointer_from_u64(virt_addr);
map(virt_addr, phys_addr, mem_len, flags);
}
}
}
efi_set_virtual_address_map svam = boot_params.efi_rt_svc->set_virtual_address_map;
assert(svam(mem_map->map_size, mem_map->desc_size, mem_map->desc_version, mem_map->map) ==
EFI_SUCCESS);

/* From now on, runtime services will only use virtual addresses: unmap physical addresses. */
for (int i = 0; i < num_desc; i++) {
efi_memory_desc d = mem_map->map + i * mem_map->desc_size;
u32 mem_type = d->type;
if ((mem_type == efi_runtime_services_code) || (mem_type == efi_runtime_services_data)) {
unmap(d->physical_start, d->number_of_pages * PAGESIZE);
}
}
boot_params.efi_rt_svc = (void *)boot_params.efi_rt_svc + rt_svc_offset;
}

static void __attribute__((noinline)) init_service_new_stack(void)
{
init_debug("in init_service_new_stack\n");
Expand All @@ -254,7 +334,10 @@ static void init_setup_stack(void)
#if 0
devicetree_dump(pointer_from_u64(DEVICETREE_BLOB_BASE));
#endif
if (boot_params.mem_map.map)
ueft_rt_init_virt();
kaslr();
kaslr_fixup_rtc(); /* needed because the RTC is initialized before KASLR */
init_debug("in init_setup_stack, calling init_kernel_heaps\n");
init_kernel_heaps();
init_debug("allocating stack\n");
Expand Down Expand Up @@ -290,21 +373,33 @@ void __attribute__((noreturn)) start(u64 x0, u64 x1)
} while (p < end);

init_debug("start\n\n");
kernel_phys_offset = u64_from_pointer(&START) - KERNEL_PHYS;
u64 device_base = 0;
if (x1) {
struct uefi_boot_params *params = pointer_from_u64(x1);
smbios_entry_point = params->smbios;
uefi_mem_map mem_map = &params->mem_map;
int num_desc = mem_map->map_size / mem_map->desc_size;
for (int i = 0; i < num_desc; i++) {
efi_memory_desc d = mem_map->map + i * mem_map->desc_size;
if (d->type == efi_memory_mapped_io) {
device_base = d->physical_start & ~(DEV_MAP_SIZE - 1);
break;
}
}
runtime_memcpy(&boot_params, params, sizeof(boot_params));
}

init_debug("calling init_mmu\n");
init_mmu(irangel(INIT_PAGEMEM, PAGESIZE_2M), u64_from_pointer(init_setup_stack));
init_mmu(device_base, u64_from_pointer(init_setup_stack));

while (1);
}

static void platform_dtb_parse(kernel_heaps kh, vector cpu_ids)
{
struct fdt fdt;
if (!dtb_parse_init(pointer_from_u64(DEVICETREE_BLOB_BASE), &fdt))
if (!dtb_parse_init(pointer_from_u64(DEVICETREE_BLOB_BASE + kernel_phys_offset), &fdt))
return;
dt_node root = fdt_get_node(&fdt);
if (!root)
Expand All @@ -327,7 +422,7 @@ static void platform_dtb_parse(kernel_heaps kh, vector cpu_ids)
map(ecam_base_virt, ecam_base, ecam_len,
pageflags_writable(pageflags_device()));
} else {
ecam_base_virt = DEVICE_BASE + ecam_base;
ecam_base_virt = DEVICE_BASE + (ecam_base & (DEV_MAP_SIZE - 1));
}
pci_platform_set_ecam(ecam_base_virt);
break;
Expand Down Expand Up @@ -358,7 +453,12 @@ closure_function(2, 2, void, plat_spcr_handler,
case SERIAL_16550_COMPATIBLE:
case SERIAL_16550_SUBSET:
case SERIAL_16550_WITH_GAS:
*bound(driver) = ns16550_console_init(bound(kh), pointer_from_u64(DEVICE_BASE + addr));
*bound(driver) = ns16550_console_init(bound(kh),
pointer_from_u64(DEVICE_BASE + (addr & (DEV_MAP_SIZE - 1))));
break;
case SERIAL_ARM_PL011:
*bound(driver) = pl011_console_init(bound(kh),
pointer_from_u64(DEVICE_BASE + (addr & (DEV_MAP_SIZE - 1))));
break;
}
}
Expand All @@ -368,7 +468,8 @@ void init_platform_devices(kernel_heaps kh)
vector cpu_ids = cpus_init_ids(heap_general(kh));
platform_dtb_parse(kh, cpu_ids);
/* the device tree blob is never accessed from now on: reclaim the memory where it is located */
id_heap_add_range(heap_physical(kh), DEVICETREE_BLOB_BASE, INIT_PAGEMEM - DEVICETREE_BLOB_BASE);
id_heap_add_range(heap_physical(kh), DEVICETREE_BLOB_BASE + kernel_phys_offset,
INIT_PAGEMEM - DEVICETREE_BLOB_BASE);
struct console_driver *console_driver = 0;
init_acpi_tables(kh);
acpi_parse_spcr(stack_closure(plat_spcr_handler, kh, &console_driver));
Expand All @@ -383,21 +484,34 @@ void init_platform_devices(kernel_heaps kh)

void detect_hypervisor(kernel_heaps kh)
{
if (hyperv_detect(kh)) {
init_debug("Hyper-V detected\n");
}
}

void detect_devices(kernel_heaps kh, storage_attach sa)
{
init_acpi(kh);
init_virtio_network(kh);
init_aws_ena(kh);
init_gve(kh);
init_virtio_blk(kh, sa);
init_virtio_scsi(kh, sa);
init_nvme(kh, sa);
init_virtio_balloon(kh);
init_virtio_rng(kh);
init_virtio_9p(kh);
init_virtio_socket(kh);
if (hyperv_detected()) {
boolean hv_storvsc_attached = false;
init_vmbus(kh);
status s = hyperv_probe_devices(sa, &hv_storvsc_attached);
if (!is_ok(s))
halt("Hyper-V probe failed: %v\n", s);
if (!hv_storvsc_attached)
msg_err("cannot detect Hyper-V storage device\n");
} else {
init_virtio_network(kh);
init_aws_ena(kh);
init_gve(kh);
init_virtio_blk(kh, sa);
init_virtio_scsi(kh, sa);
init_nvme(kh, sa);
init_virtio_balloon(kh);
init_virtio_rng(kh);
init_virtio_9p(kh);
init_virtio_socket(kh);
}
if (!vm_halt) {
vm_halt = closure_func(heap_locked(kh), halt_handler, psci_vm_halt);
assert(vm_halt != INVALID_ADDRESS);
Expand Down
24 changes: 22 additions & 2 deletions src/aarch64/crt0.S
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,9 @@ aarch64_cpu_init:
msr cpacr_el1, x0

// temporary stack
mov x0, (PHYSMEM_BASE + INIT_IDENTITY_SIZE)
mov sp, x0
adr x0, #0
and x0, x0, ~PHYSMEM_BASE_MASK
add sp, x0, INIT_IDENTITY_SIZE

ret

Expand Down Expand Up @@ -185,6 +186,25 @@ arm_hvc:
hvc #0
ret

.globl arm_hvc_full
arm_hvc_full:
sub sp, sp, #0x10
stp x8, x19, [sp]
hvc #0
ldr x19, [sp]
stp x0, x1, [x19]
stp x2, x3, [x19, #0x10]
stp x4, x5, [x19, #0x20]
stp x6, x7, [x19, #0x30]
stp x8, x9, [x19, #0x40]
stp x10, x11, [x19, #0x50]
stp x12, x13, [x19, #0x60]
stp x14, x15, [x19, #0x70]
stp x16, x17, [x19, #0x80]
ldr x19, [sp, #8]
add sp, sp, #0x10
ret

.macro vector path
.align 7
b entry_\path
Expand Down
Loading