aboutsummaryrefslogtreecommitdiff
path: root/arch/tile/include/hv/hypervisor.h
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2010-05-28 23:09:12 -0400
committerChris Metcalf <cmetcalf@tilera.com>2010-06-04 17:11:18 -0400
commit867e359b97c970a60626d5d76bbe2a8fadbf38fb (patch)
treec5ccbb7f5172e8555977119608ecb1eee3cc37e3 /arch/tile/include/hv/hypervisor.h
parent5360bd776f73d0a7da571d72a09a03f237e99900 (diff)
arch/tile: core support for Tilera 32-bit chips.
This change is the core kernel support for TILEPro and TILE64 chips. No driver support (except the console driver) is included yet. This includes the relevant Linux headers in asm/; the low-level low-level "Tile architecture" headers in arch/, which are shared with the hypervisor, etc., and are build-system agnostic; and the relevant hypervisor headers in hv/. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com> Acked-by: Arnd Bergmann <arnd@arndb.de> Acked-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp> Reviewed-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/tile/include/hv/hypervisor.h')
-rw-r--r--arch/tile/include/hv/hypervisor.h2366
1 files changed, 2366 insertions, 0 deletions
diff --git a/arch/tile/include/hv/hypervisor.h b/arch/tile/include/hv/hypervisor.h
new file mode 100644
index 00000000000..84b31551080
--- /dev/null
+++ b/arch/tile/include/hv/hypervisor.h
@@ -0,0 +1,2366 @@
+/*
+ * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT. See the GNU General Public License for
+ * more details.
+ */
+
+/**
+ * @file hypervisor.h
+ * The hypervisor's public API.
+ */
+
+#ifndef _TILE_HV_H
+#define _TILE_HV_H
+
+#ifdef __tile__
+#include <arch/chip.h>
+#else
+/* HACK: Allow use by "tools/cpack/". */
+#include "install/include/arch/chip.h"
+#endif
+
+/* Linux builds want unsigned long constants, but assembler wants numbers */
+#ifdef __ASSEMBLER__
+/** One, for assembler */
+#define __HV_SIZE_ONE 1
+#elif !defined(__tile__) && CHIP_VA_WIDTH() > 32
+/** One, for 64-bit on host */
+#define __HV_SIZE_ONE 1ULL
+#else
+/** One, for Linux */
+#define __HV_SIZE_ONE 1UL
+#endif
+
+
+/** The log2 of the span of a level-1 page table, in bytes.
+ */
+#define HV_LOG2_L1_SPAN 32
+
+/** The span of a level-1 page table, in bytes.
+ */
+#define HV_L1_SPAN (__HV_SIZE_ONE << HV_LOG2_L1_SPAN)
+
+/** The log2 of the size of small pages, in bytes. This value should
+ * be verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL).
+ */
+#define HV_LOG2_PAGE_SIZE_SMALL 16
+
+/** The size of small pages, in bytes. This value should be verified
+ * at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_SMALL).
+ */
+#define HV_PAGE_SIZE_SMALL (__HV_SIZE_ONE << HV_LOG2_PAGE_SIZE_SMALL)
+
+/** The log2 of the size of large pages, in bytes. This value should be
+ * verified at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE).
+ */
+#define HV_LOG2_PAGE_SIZE_LARGE 24
+
+/** The size of large pages, in bytes. This value should be verified
+ * at runtime by calling hv_sysconf(HV_SYSCONF_PAGE_SIZE_LARGE).
+ */
+#define HV_PAGE_SIZE_LARGE (__HV_SIZE_ONE << HV_LOG2_PAGE_SIZE_LARGE)
+
+/** The log2 of the granularity at which page tables must be aligned;
+ * in other words, the CPA for a page table must have this many zero
+ * bits at the bottom of the address.
+ */
+#define HV_LOG2_PAGE_TABLE_ALIGN 11
+
+/** The granularity at which page tables must be aligned.
+ */
+#define HV_PAGE_TABLE_ALIGN (__HV_SIZE_ONE << HV_LOG2_PAGE_TABLE_ALIGN)
+
+/** Normal start of hypervisor glue in client physical memory. */
+#define HV_GLUE_START_CPA 0x10000
+
+/** This much space is reserved at HV_GLUE_START_CPA
+ * for the hypervisor glue. The client program must start at
+ * some address higher than this, and in particular the address of
+ * its text section should be equal to zero modulo HV_PAGE_SIZE_LARGE
+ * so that relative offsets to the HV glue are correct.
+ */
+#define HV_GLUE_RESERVED_SIZE 0x10000
+
+/** Each entry in the hv dispatch array takes this many bytes. */
+#define HV_DISPATCH_ENTRY_SIZE 32
+
+/** Version of the hypervisor interface defined by this file */
+#define _HV_VERSION 10
+
+/* Index into hypervisor interface dispatch code blocks.
+ *
+ * Hypervisor calls are invoked from user space by calling code
+ * at an address HV_BASE_ADDRESS + (index) * HV_DISPATCH_ENTRY_SIZE,
+ * where index is one of these enum values.
+ *
+ * Normally a supervisor is expected to produce a set of symbols
+ * starting at HV_BASE_ADDRESS that obey this convention, but a user
+ * program could call directly through function pointers if desired.
+ *
+ * These numbers are part of the binary API and will not be changed
+ * without updating HV_VERSION, which should be a rare event.
+ */
+
+/** reserved. */
+#define _HV_DISPATCH_RESERVED 0
+
+/** hv_init */
+#define HV_DISPATCH_INIT 1
+
+/** hv_install_context */
+#define HV_DISPATCH_INSTALL_CONTEXT 2
+
+/** hv_sysconf */
+#define HV_DISPATCH_SYSCONF 3
+
+/** hv_get_rtc */
+#define HV_DISPATCH_GET_RTC 4
+
+/** hv_set_rtc */
+#define HV_DISPATCH_SET_RTC 5
+
+/** hv_flush_asid */
+#define HV_DISPATCH_FLUSH_ASID 6
+
+/** hv_flush_page */
+#define HV_DISPATCH_FLUSH_PAGE 7
+
+/** hv_flush_pages */
+#define HV_DISPATCH_FLUSH_PAGES 8
+
+/** hv_restart */
+#define HV_DISPATCH_RESTART 9
+
+/** hv_halt */
+#define HV_DISPATCH_HALT 10
+
+/** hv_power_off */
+#define HV_DISPATCH_POWER_OFF 11
+
+/** hv_inquire_physical */
+#define HV_DISPATCH_INQUIRE_PHYSICAL 12
+
+/** hv_inquire_memory_controller */
+#define HV_DISPATCH_INQUIRE_MEMORY_CONTROLLER 13
+
+/** hv_inquire_virtual */
+#define HV_DISPATCH_INQUIRE_VIRTUAL 14
+
+/** hv_inquire_asid */
+#define HV_DISPATCH_INQUIRE_ASID 15
+
+/** hv_nanosleep */
+#define HV_DISPATCH_NANOSLEEP 16
+
+/** hv_console_read_if_ready */
+#define HV_DISPATCH_CONSOLE_READ_IF_READY 17
+
+/** hv_console_write */
+#define HV_DISPATCH_CONSOLE_WRITE 18
+
+/** hv_downcall_dispatch */
+#define HV_DISPATCH_DOWNCALL_DISPATCH 19
+
+/** hv_inquire_topology */
+#define HV_DISPATCH_INQUIRE_TOPOLOGY 20
+
+/** hv_fs_findfile */
+#define HV_DISPATCH_FS_FINDFILE 21
+
+/** hv_fs_fstat */
+#define HV_DISPATCH_FS_FSTAT 22
+
+/** hv_fs_pread */
+#define HV_DISPATCH_FS_PREAD 23
+
+/** hv_physaddr_read64 */
+#define HV_DISPATCH_PHYSADDR_READ64 24
+
+/** hv_physaddr_write64 */
+#define HV_DISPATCH_PHYSADDR_WRITE64 25
+
+/** hv_get_command_line */
+#define HV_DISPATCH_GET_COMMAND_LINE 26
+
+/** hv_set_caching */
+#define HV_DISPATCH_SET_CACHING 27
+
+/** hv_bzero_page */
+#define HV_DISPATCH_BZERO_PAGE 28
+
+/** hv_register_message_state */
+#define HV_DISPATCH_REGISTER_MESSAGE_STATE 29
+
+/** hv_send_message */
+#define HV_DISPATCH_SEND_MESSAGE 30
+
+/** hv_receive_message */
+#define HV_DISPATCH_RECEIVE_MESSAGE 31
+
+/** hv_inquire_context */
+#define HV_DISPATCH_INQUIRE_CONTEXT 32
+
+/** hv_start_all_tiles */
+#define HV_DISPATCH_START_ALL_TILES 33
+
+/** hv_dev_open */
+#define HV_DISPATCH_DEV_OPEN 34
+
+/** hv_dev_close */
+#define HV_DISPATCH_DEV_CLOSE 35
+
+/** hv_dev_pread */
+#define HV_DISPATCH_DEV_PREAD 36
+
+/** hv_dev_pwrite */
+#define HV_DISPATCH_DEV_PWRITE 37
+
+/** hv_dev_poll */
+#define HV_DISPATCH_DEV_POLL 38
+
+/** hv_dev_poll_cancel */
+#define HV_DISPATCH_DEV_POLL_CANCEL 39
+
+/** hv_dev_preada */
+#define HV_DISPATCH_DEV_PREADA 40
+
+/** hv_dev_pwritea */
+#define HV_DISPATCH_DEV_PWRITEA 41
+
+/** hv_flush_remote */
+#define HV_DISPATCH_FLUSH_REMOTE 42
+
+/** hv_console_putc */
+#define HV_DISPATCH_CONSOLE_PUTC 43
+
+/** hv_inquire_tiles */
+#define HV_DISPATCH_INQUIRE_TILES 44
+
+/** hv_confstr */
+#define HV_DISPATCH_CONFSTR 45
+
+/** hv_reexec */
+#define HV_DISPATCH_REEXEC 46
+
+/** hv_set_command_line */
+#define HV_DISPATCH_SET_COMMAND_LINE 47
+
+/** hv_dev_register_intr_state */
+#define HV_DISPATCH_DEV_REGISTER_INTR_STATE 48
+
+/** hv_enable_intr */
+#define HV_DISPATCH_ENABLE_INTR 49
+
+/** hv_disable_intr */
+#define HV_DISPATCH_DISABLE_INTR 50
+
+/** hv_trigger_ipi */
+#define HV_DISPATCH_TRIGGER_IPI 51
+
+/** hv_store_mapping */
+#define HV_DISPATCH_STORE_MAPPING 52
+
+/** hv_inquire_realpa */
+#define HV_DISPATCH_INQUIRE_REALPA 53
+
+/** hv_flush_all */
+#define HV_DISPATCH_FLUSH_ALL 54
+
+/** One more than the largest dispatch value */
+#define _HV_DISPATCH_END 55
+
+
+#ifndef __ASSEMBLER__
+
+#ifdef __KERNEL__
+#include <asm/types.h>
+typedef u32 __hv32; /**< 32-bit value */
+typedef u64 __hv64; /**< 64-bit value */
+#else
+#include <stdint.h>
+typedef uint32_t __hv32; /**< 32-bit value */
+typedef uint64_t __hv64; /**< 64-bit value */
+#endif
+
+
+/** Hypervisor physical address. */
+typedef __hv64 HV_PhysAddr;
+
+#if CHIP_VA_WIDTH() > 32
+/** Hypervisor virtual address. */
+typedef __hv64 HV_VirtAddr;
+#else
+/** Hypervisor virtual address. */
+typedef __hv32 HV_VirtAddr;
+#endif /* CHIP_VA_WIDTH() > 32 */
+
+/** Hypervisor ASID. */
+typedef unsigned int HV_ASID;
+
+/** Hypervisor tile location for a memory access
+ * ("location overridden target").
+ */
+typedef unsigned int HV_LOTAR;
+
+/** Hypervisor size of a page. */
+typedef unsigned long HV_PageSize;
+
+/** A page table entry.
+ */
+typedef struct
+{
+ __hv64 val; /**< Value of PTE */
+} HV_PTE;
+
+/** Hypervisor error code. */
+typedef int HV_Errno;
+
+#endif /* !__ASSEMBLER__ */
+
+#define HV_OK 0 /**< No error */
+#define HV_EINVAL -801 /**< Invalid argument */
+#define HV_ENODEV -802 /**< No such device */
+#define HV_ENOENT -803 /**< No such file or directory */
+#define HV_EBADF -804 /**< Bad file number */
+#define HV_EFAULT -805 /**< Bad address */
+#define HV_ERECIP -806 /**< Bad recipients */
+#define HV_E2BIG -807 /**< Message too big */
+#define HV_ENOTSUP -808 /**< Service not supported */
+#define HV_EBUSY -809 /**< Device busy */
+#define HV_ENOSYS -810 /**< Invalid syscall */
+#define HV_EPERM -811 /**< No permission */
+#define HV_ENOTREADY -812 /**< Device not ready */
+#define HV_EIO -813 /**< I/O error */
+#define HV_ENOMEM -814 /**< Out of memory */
+
+#define HV_ERR_MAX -801 /**< Largest HV error code */
+#define HV_ERR_MIN -814 /**< Smallest HV error code */
+
+#ifndef __ASSEMBLER__
+
+/** Pass HV_VERSION to hv_init to request this version of the interface. */
+typedef enum { HV_VERSION = _HV_VERSION } HV_VersionNumber;
+
+/** Initializes the hypervisor.
+ *
+ * @param interface_version_number The version of the hypervisor interface
+ * that this program expects, typically HV_VERSION.
+ * @param chip_num Architecture number of the chip the client was built for.
+ * @param chip_rev_num Revision number of the chip the client was built for.
+ */
+void hv_init(HV_VersionNumber interface_version_number,
+ int chip_num, int chip_rev_num);
+
+
+/** Queries we can make for hv_sysconf().
+ *
+ * These numbers are part of the binary API and guaranteed not to change.
+ */
+typedef enum {
+ /** An invalid value; do not use. */
+ _HV_SYSCONF_RESERVED = 0,
+
+ /** The length of the glue section containing the hv_ procs, in bytes. */
+ HV_SYSCONF_GLUE_SIZE = 1,
+
+ /** The size of small pages, in bytes. */
+ HV_SYSCONF_PAGE_SIZE_SMALL = 2,
+
+ /** The size of large pages, in bytes. */
+ HV_SYSCONF_PAGE_SIZE_LARGE = 3,
+
+ /** Processor clock speed, in hertz. */
+ HV_SYSCONF_CPU_SPEED = 4,
+
+ /** Processor temperature, in degrees Kelvin. The value
+ * HV_SYSCONF_TEMP_KTOC may be subtracted from this to get degrees
+ * Celsius. If that Celsius value is HV_SYSCONF_OVERTEMP, this indicates
+ * that the temperature has hit an upper limit and is no longer being
+ * accurately tracked.
+ */
+ HV_SYSCONF_CPU_TEMP = 5,
+
+ /** Board temperature, in degrees Kelvin. The value
+ * HV_SYSCONF_TEMP_KTOC may be subtracted from this to get degrees
+ * Celsius. If that Celsius value is HV_SYSCONF_OVERTEMP, this indicates
+ * that the temperature has hit an upper limit and is no longer being
+ * accurately tracked.
+ */
+ HV_SYSCONF_BOARD_TEMP = 6
+
+} HV_SysconfQuery;
+
+/** Offset to subtract from returned Kelvin temperature to get degrees
+ Celsius. */
+#define HV_SYSCONF_TEMP_KTOC 273
+
+/** Pseudo-temperature value indicating that the temperature has
+ * pegged at its upper limit and is no longer accurate; note that this is
+ * the value after subtracting HV_SYSCONF_TEMP_KTOC. */
+#define HV_SYSCONF_OVERTEMP 999
+
+/** Query a configuration value from the hypervisor.
+ * @param query Which value is requested (HV_SYSCONF_xxx).
+ * @return The requested value, or -1 the requested value is illegal or
+ * unavailable.
+ */
+long hv_sysconf(HV_SysconfQuery query);
+
+
+/** Queries we can make for hv_confstr().
+ *
+ * These numbers are part of the binary API and guaranteed not to change.
+ */
+typedef enum {
+ /** An invalid value; do not use. */
+ _HV_CONFSTR_RESERVED = 0,
+
+ /** Board part number. */
+ HV_CONFSTR_BOARD_PART_NUM = 1,
+
+ /** Board serial number. */
+ HV_CONFSTR_BOARD_SERIAL_NUM = 2,
+
+ /** Chip serial number. */
+ HV_CONFSTR_CHIP_SERIAL_NUM = 3,
+
+ /** Board revision level. */
+ HV_CONFSTR_BOARD_REV = 4,
+
+ /** Hypervisor software version. */
+ HV_CONFSTR_HV_SW_VER = 5,
+
+ /** The name for this chip model. */
+ HV_CONFSTR_CHIP_MODEL = 6,
+
+ /** Human-readable board description. */
+ HV_CONFSTR_BOARD_DESC = 7,
+
+ /** Human-readable description of the hypervisor configuration. */
+ HV_CONFSTR_HV_CONFIG = 8,
+
+ /** Human-readable version string for the boot image (for instance,
+ * who built it and when, what configuration file was used). */
+ HV_CONFSTR_HV_CONFIG_VER = 9,
+
+ /** Mezzanine part number. */
+ HV_CONFSTR_MEZZ_PART_NUM = 10,
+
+ /** Mezzanine serial number. */
+ HV_CONFSTR_MEZZ_SERIAL_NUM = 11,
+
+ /** Mezzanine revision level. */
+ HV_CONFSTR_MEZZ_REV = 12,
+
+ /** Human-readable mezzanine description. */
+ HV_CONFSTR_MEZZ_DESC = 13,
+
+ /** Control path for the onboard network switch. */
+ HV_CONFSTR_SWITCH_CONTROL = 14,
+
+ /** Chip revision level. */
+ HV_CONFSTR_CHIP_REV = 15
+
+} HV_ConfstrQuery;
+
+/** Query a configuration string from the hypervisor.
+ *
+ * @param query Identifier for the specific string to be retrieved
+ * (HV_CONFSTR_xxx).
+ * @param buf Buffer in which to place the string.
+ * @param len Length of the buffer.
+ * @return If query is valid, then the length of the corresponding string,
+ * including the trailing null; if this is greater than len, the string
+ * was truncated. If query is invalid, HV_EINVAL. If the specified
+ * buffer is not writable by the client, HV_EFAULT.
+ */
+int hv_confstr(HV_ConfstrQuery query, HV_VirtAddr buf, int len);
+
+/** State object used to enable and disable one-shot and level-sensitive
+ * interrupts. */
+typedef struct
+{
+#if CHIP_VA_WIDTH() > 32
+ __hv64 opaque[2]; /**< No user-serviceable parts inside */
+#else
+ __hv32 opaque[2]; /**< No user-serviceable parts inside */
+#endif
+}
+HV_IntrState;
+
+/** A set of interrupts. */
+typedef __hv32 HV_IntrMask;
+
+/** Tile coordinate */
+typedef struct
+{
+ /** X coordinate, relative to supervisor's top-left coordinate */
+ int x;
+
+ /** Y coordinate, relative to supervisor's top-left coordinate */
+ int y;
+} HV_Coord;
+
+/** The low interrupt numbers are reserved for use by the client in
+ * delivering IPIs. Any interrupt numbers higher than this value are
+ * reserved for use by HV device drivers. */
+#define HV_MAX_IPI_INTERRUPT 7
+
+/** Register an interrupt state object. This object is used to enable and
+ * disable one-shot and level-sensitive interrupts. Once the state is
+ * registered, the client must not read or write the state object; doing
+ * so will cause undefined results.
+ *
+ * @param intr_state Pointer to interrupt state object.
+ * @return HV_OK on success, or a hypervisor error code.
+ */
+HV_Errno hv_dev_register_intr_state(HV_IntrState* intr_state);
+
+/** Enable a set of one-shot and level-sensitive interrupts.
+ *
+ * @param intr_state Pointer to interrupt state object.
+ * @param enab_mask Bitmap of interrupts to enable.
+ */
+void hv_enable_intr(HV_IntrState* intr_state, HV_IntrMask enab_mask);
+
+/** Disable a set of one-shot and level-sensitive interrupts.
+ *
+ * @param intr_state Pointer to interrupt state object.
+ * @param disab_mask Bitmap of interrupts to disable.
+ */
+void hv_disable_intr(HV_IntrState* intr_state, HV_IntrMask disab_mask);
+
+/** Trigger a one-shot interrupt on some tile
+ *
+ * @param tile Which tile to interrupt.
+ * @param interrupt Interrupt number to trigger; must be between 0 and
+ * HV_MAX_IPI_INTERRUPT.
+ * @return HV_OK on success, or a hypervisor error code.
+ */
+HV_Errno hv_trigger_ipi(HV_Coord tile, int interrupt);
+
+/** Store memory mapping in debug memory so that external debugger can read it.
+ * A maximum of 16 entries can be stored.
+ *
+ * @param va VA of memory that is mapped.
+ * @param len Length of mapped memory.
+ * @param pa PA of memory that is mapped.
+ * @return 0 on success, -1 if the maximum number of mappings is exceeded.
+ */
+int hv_store_mapping(HV_VirtAddr va, unsigned int len, HV_PhysAddr pa);
+
+/** Given a client PA and a length, return its real (HV) PA.
+ *
+ * @param cpa Client physical address.
+ * @param len Length of mapped memory.
+ * @return physical address, or -1 if cpa or len is not valid.
+ */
+HV_PhysAddr hv_inquire_realpa(HV_PhysAddr cpa, unsigned int len);
+
+/** RTC return flag for no RTC chip present.
+ */
+#define HV_RTC_NO_CHIP 0x1
+
+/** RTC return flag for low-voltage condition, indicating that battery had
+ * died and time read is unreliable.
+ */
+#define HV_RTC_LOW_VOLTAGE 0x2
+
+/** Date/Time of day */
+typedef struct {
+#if CHIP_WORD_SIZE() > 32
+ __hv64 tm_sec; /**< Seconds, 0-59 */
+ __hv64 tm_min; /**< Minutes, 0-59 */
+ __hv64 tm_hour; /**< Hours, 0-23 */
+ __hv64 tm_mday; /**< Day of month, 0-30 */
+ __hv64 tm_mon; /**< Month, 0-11 */
+ __hv64 tm_year; /**< Years since 1900, 0-199 */
+ __hv64 flags; /**< Return flags, 0 if no error */
+#else
+ __hv32 tm_sec; /**< Seconds, 0-59 */
+ __hv32 tm_min; /**< Minutes, 0-59 */
+ __hv32 tm_hour; /**< Hours, 0-23 */
+ __hv32 tm_mday; /**< Day of month, 0-30 */
+ __hv32 tm_mon; /**< Month, 0-11 */
+ __hv32 tm_year; /**< Years since 1900, 0-199 */
+ __hv32 flags; /**< Return flags, 0 if no error */
+#endif
+} HV_RTCTime;
+
+/** Read the current time-of-day clock.
+ * @return HV_RTCTime of current time (GMT).
+ */
+HV_RTCTime hv_get_rtc(void);
+
+
+/** Set the current time-of-day clock.
+ * @param time time to reset time-of-day to (GMT).
+ */
+void hv_set_rtc(HV_RTCTime time);
+
+/** Installs a context, comprising a page table and other attributes.
+ *
+ * Once this service completes, page_table will be used to translate
+ * subsequent virtual address references to physical memory.
+ *
+ * Installing a context does not cause an implicit TLB flush. Before
+ * reusing an ASID value for a different address space, the client is
+ * expected to flush old references from the TLB with hv_flush_asid().
+ * (Alternately, hv_flush_all() may be used to flush many ASIDs at once.)
+ * After invalidating a page table entry, changing its attributes, or
+ * changing its target CPA, the client is expected to flush old references
+ * from the TLB with hv_flush_page() or hv_flush_pages(). Making a
+ * previously invalid page valid does not require a flush.
+ *
+ * Specifying an invalid ASID, or an invalid CPA (client physical address)
+ * (either as page_table_pointer, or within the referenced table),
+ * or another page table data item documented as above as illegal may
+ * lead to client termination; since the validation of the table is
+ * done as needed, this may happen before the service returns, or at
+ * some later time, or never, depending upon the client's pattern of
+ * memory references. Page table entries which supply translations for
+ * invalid virtual addresses may result in client termination, or may
+ * be silently ignored. "Invalid" in this context means a value which
+ * was not provided to the client via the appropriate hv_inquire_* routine.
+ *
+ * To support changing the instruction VAs at the same time as
+ * installing the new page table, this call explicitly supports
+ * setting the "lr" register to a different address and then jumping
+ * directly to the hv_install_context() routine. In this case, the
+ * new page table does not need to contain any mapping for the
+ * hv_install_context address itself.
+ *
+ * @param page_table Root of the page table.
+ * @param access PTE providing info on how to read the page table. This
+ * value must be consistent between multiple tiles sharing a page table,
+ * and must also be consistent with any virtual mappings the client
+ * may be using to access the page table.
+ * @param asid HV_ASID the page table is to be used for.
+ * @param flags Context flags, denoting attributes or privileges of the
+ * current context (HV_CTX_xxx).
+ * @return Zero on success, or a hypervisor error code on failure.
+ */
+int hv_install_context(HV_PhysAddr page_table, HV_PTE access, HV_ASID asid,
+ __hv32 flags);
+
+#endif /* !__ASSEMBLER__ */
+
+#define HV_CTX_DIRECTIO 0x1 /**< Direct I/O requests are accepted from
+ PL0. */
+
+#ifndef __ASSEMBLER__
+
+/** Value returned from hv_inquire_context(). */
+typedef struct
+{
+ /** Physical address of page table */
+ HV_PhysAddr page_table;
+
+ /** PTE which defines access method for top of page table */
+ HV_PTE access;
+
+ /** ASID associated with this page table */
+ HV_ASID asid;
+
+ /** Context flags */
+ __hv32 flags;
+} HV_Context;
+
+/** Retrieve information about the currently installed context.
+ * @return The data passed to the last successful hv_install_context call.
+ */
+HV_Context hv_inquire_context(void);
+
+
+/** Flushes all translations associated with the named address space
+ * identifier from the TLB and any other hypervisor data structures.
+ * Translations installed with the "global" bit are not flushed.
+ *
+ * Specifying an invalid ASID may lead to client termination. "Invalid"
+ * in this context means a value which was not provided to the client
+ * via <tt>hv_inquire_asid()</tt>.
+ *
+ * @param asid HV_ASID whose entries are to be flushed.
+ * @return Zero on success, or a hypervisor error code on failure.
+*/
+int hv_flush_asid(HV_ASID asid);
+
+
+/** Flushes all translations associated with the named virtual address
+ * and page size from the TLB and other hypervisor data structures. Only
+ * pages visible to the current ASID are affected; note that this includes
+ * global pages in addition to pages specific to the current ASID.
+ *
+ * The supplied VA need not be aligned; it may be anywhere in the
+ * subject page.
+ *
+ * Specifying an invalid virtual address may lead to client termination,
+ * or may silently succeed. "Invalid" in this context means a value
+ * which was not provided to the client via hv_inquire_virtual.
+ *
+ * @param address Address of the page to flush.
+ * @param page_size Size of pages to assume.
+ * @return Zero on success, or a hypervisor error code on failure.
+ */
+int hv_flush_page(HV_VirtAddr address, HV_PageSize page_size);
+
+
+/** Flushes all translations associated with the named virtual address range
+ * and page size from the TLB and other hypervisor data structures. Only
+ * pages visible to the current ASID are affected; note that this includes
+ * global pages in addition to pages specific to the current ASID.
+ *
+ * The supplied VA need not be aligned; it may be anywhere in the
+ * subject page.
+ *
+ * Specifying an invalid virtual address may lead to client termination,
+ * or may silently succeed. "Invalid" in this context means a value
+ * which was not provided to the client via hv_inquire_virtual.
+ *
+ * @param start Address to flush.
+ * @param page_size Size of pages to assume.
+ * @param size The number of bytes to flush. Any page in the range
+ * [start, start + size) will be flushed from the TLB.
+ * @return Zero on success, or a hypervisor error code on failure.
+ */
+int hv_flush_pages(HV_VirtAddr start, HV_PageSize page_size,
+ unsigned long size);
+
+
+/** Flushes all non-global translations (if preserve_global is true),
+ * or absolutely all translations (if preserve_global is false).
+ *
+ * @param preserve_global Non-zero if we want to preserve "global" mappings.
+ * @return Zero on success, or a hypervisor error code on failure.
+*/
+int hv_flush_all(int preserve_global);
+
+
+/** Restart machine with optional restart command and optional args.
+ * @param cmd Const pointer to command to restart with, or NULL
+ * @param args Const pointer to argument string to restart with, or NULL
+ */
+void hv_restart(HV_VirtAddr cmd, HV_VirtAddr args);
+
+
+/** Halt machine. */
+void hv_halt(void);
+
+
+/** Power off machine. */
+void hv_power_off(void);
+
+
+/** Re-enter virtual-is-physical memory translation mode and restart
+ * execution at a given address.
+ * @param entry Client physical address at which to begin execution.
+ * @return A hypervisor error code on failure; if the operation is
+ * successful the call does not return.
+ */
+int hv_reexec(HV_PhysAddr entry);
+
+
+/** Chip topology */
+typedef struct
+{
+ /** Relative coordinates of the querying tile */
+ HV_Coord coord;
+
+ /** Width of the querying supervisor's tile rectangle. */
+ int width;
+
+ /** Height of the querying supervisor's tile rectangle. */
+ int height;
+
+} HV_Topology;
+
+/** Returns information about the tile coordinate system.
+ *
+ * Each supervisor is given a rectangle of tiles it potentially controls.
+ * These tiles are labeled using a relative coordinate system with (0,0) as
+ * the upper left tile regardless of their physical location on the chip.
+ *
+ * This call returns both the size of that rectangle and the position
+ * within that rectangle of the querying tile.
+ *
+ * Not all tiles within that rectangle may be available to the supervisor;
+ * to get the precise set of available tiles, you must also call
+ * hv_inquire_tiles(HV_INQ_TILES_AVAIL, ...).
+ **/
+HV_Topology hv_inquire_topology(void);
+
+/** Sets of tiles we can retrieve with hv_inquire_tiles().
+ *
+ * These numbers are part of the binary API and guaranteed not to change.
+ */
+typedef enum {
+ /** An invalid value; do not use. */
+ _HV_INQ_TILES_RESERVED = 0,
+
+ /** All available tiles within the supervisor's tile rectangle. */
+ HV_INQ_TILES_AVAIL = 1,
+
+ /** The set of tiles used for hash-for-home caching. */
+ HV_INQ_TILES_HFH_CACHE = 2,
+
+ /** The set of tiles that can be legally used as a LOTAR for a PTE. */
+ HV_INQ_TILES_LOTAR = 3
+} HV_InqTileSet;
+
+/** Returns specific information about various sets of tiles within the
+ * supervisor's tile rectangle.
+ *
+ * @param set Which set of tiles to retrieve.
+ * @param cpumask Pointer to a returned bitmask (in row-major order,
+ * supervisor-relative) of tiles. The low bit of the first word
+ * corresponds to the tile at the upper left-hand corner of the
+ * supervisor's rectangle. In order for the supervisor to know the
+ * buffer length to supply, it should first call hv_inquire_topology.
+ * @param length Number of bytes available for the returned bitmask.
+ **/
+HV_Errno hv_inquire_tiles(HV_InqTileSet set, HV_VirtAddr cpumask, int length);
+
+
+/** An identifier for a memory controller. Multiple memory controllers
+ * may be connected to one chip, and this uniquely identifies each one.
+ */
+typedef int HV_MemoryController;
+
+/** A range of physical memory. */
+typedef struct
+{
+ HV_PhysAddr start; /**< Starting address. */
+ __hv64 size; /**< Size in bytes. */
+ HV_MemoryController controller; /**< Which memory controller owns this. */
+} HV_PhysAddrRange;
+
+/** Returns information about a range of physical memory.
+ *
+ * hv_inquire_physical() returns one of the ranges of client
+ * physical addresses which are available to this client.
+ *
+ * The first range is retrieved by specifying an idx of 0, and
+ * successive ranges are returned with subsequent idx values. Ranges
+ * are ordered by increasing start address (i.e., as idx increases,
+ * so does start), do not overlap, and do not touch (i.e., the
+ * available memory is described with the fewest possible ranges).
+ *
+ * If an out-of-range idx value is specified, the returned size will be zero.
+ * A client can count the number of ranges by increasing idx until the
+ * returned size is zero. There will always be at least one valid range.
+ *
+ * Some clients might not be prepared to deal with more than one
+ * physical address range; they still ought to call this routine and
+ * issue a warning message if they're given more than one range, on the
+ * theory that whoever configured the hypervisor to provide that memory
+ * should know that it's being wasted.
+ */
+HV_PhysAddrRange hv_inquire_physical(int idx);
+
+
+/** Memory controller information. */
+typedef struct
+{
+ HV_Coord coord; /**< Relative tile coordinates of the port used by a
+ specified tile to communicate with this controller. */
+ __hv64 speed; /**< Speed of this controller in bytes per second. */
+} HV_MemoryControllerInfo;
+
+/** Returns information about a particular memory controller.
+ *
+ * hv_inquire_memory_controller(coord,idx) returns information about a
+ * particular controller. Two pieces of information are returned:
+ * - The relative coordinates of the port on the controller that the specified
+ * tile would use to contact it. The relative coordinates may lie
+ * outside the supervisor's rectangle, i.e. the controller may not
+ * be attached to a node managed by the querying node's supervisor.
+ * In particular note that x or y may be negative.
+ * - The speed of the memory controller. (This is a not-to-exceed value
+ * based on the raw hardware data rate, and may not be achievable in
+ * practice; it is provided to give clients information on the relative
+ * performance of the available controllers.)
+ *
+ * Clients should avoid calling this interface with invalid values.
+ * A client who does may be terminated.
+ * @param coord Tile for which to calculate the relative port position.
+ * @param controller Index of the controller; identical to value returned
+ * from other routines like hv_inquire_physical.
+ * @return Information about the controller.
+ */
+HV_MemoryControllerInfo hv_inquire_memory_controller(HV_Coord coord,
+ int controller);
+
+
+/** A range of virtual memory. */
+typedef struct
+{
+ HV_VirtAddr start; /**< Starting address. */
+ __hv64 size; /**< Size in bytes. */
+} HV_VirtAddrRange;
+
+/** Returns information about a range of virtual memory.
+ *
+ * hv_inquire_virtual() returns one of the ranges of client
+ * virtual addresses which are available to this client.
+ *
+ * The first range is retrieved by specifying an idx of 0, and
+ * successive ranges are returned with subsequent idx values. Ranges
+ * are ordered by increasing start address (i.e., as idx increases,
+ * so does start), do not overlap, and do not touch (i.e., the
+ * available memory is described with the fewest possible ranges).
+ *
+ * If an out-of-range idx value is specified, the returned size will be zero.
+ * A client can count the number of ranges by increasing idx until the
+ * returned size is zero. There will always be at least one valid range.
+ *
+ * Some clients may well have various virtual addresses hardwired
+ * into themselves; for instance, their instruction stream may
+ * have been compiled expecting to live at a particular address.
+ * Such clients should use this interface to verify they've been
+ * given the virtual address space they expect, and issue a (potentially
+ * fatal) warning message otherwise.
+ *
+ * Note that the returned size is a __hv64, not a __hv32, so it is
+ * possible to express a single range spanning the entire 32-bit
+ * address space.
+ */
+HV_VirtAddrRange hv_inquire_virtual(int idx);
+
+
+/** A range of ASID values. */
+typedef struct
+{
+ HV_ASID start; /**< First ASID in the range. */
+ unsigned int size; /**< Number of ASIDs. Zero for an invalid range. */
+} HV_ASIDRange;
+
+/** Returns information about a range of ASIDs.
+ *
+ * hv_inquire_asid() returns one of the ranges of address
+ * space identifiers which are available to this client.
+ *
+ * The first range is retrieved by specifying an idx of 0, and
+ * successive ranges are returned with subsequent idx values. Ranges
+ * are ordered by increasing start value (i.e., as idx increases,
+ * so does start), do not overlap, and do not touch (i.e., the
+ * available ASIDs are described with the fewest possible ranges).
+ *
+ * If an out-of-range idx value is specified, the returned size will be zero.
+ * A client can count the number of ranges by increasing idx until the
+ * returned size is zero. There will always be at least one valid range.
+ */
+HV_ASIDRange hv_inquire_asid(int idx);
+
+
+/** Waits for at least the specified number of nanoseconds then returns.
+ *
+ * @param nanosecs The number of nanoseconds to sleep.
+ */
+void hv_nanosleep(int nanosecs);
+
+
+/** Reads a character from the console without blocking.
+ *
+ * @return A value from 0-255 indicates the value successfully read.
+ * A negative value means no value was ready.
+ */
+int hv_console_read_if_ready(void);
+
+
+/** Writes a character to the console, blocking if the console is busy.
+ *
+ * This call cannot fail. If the console is broken for some reason,
+ * output will simply vanish.
+ * @param byte Character to write.
+ */
+void hv_console_putc(int byte);
+
+
+/** Writes a string to the console, blocking if the console is busy.
+ * @param bytes Pointer to characters to write.
+ * @param len Number of characters to write.
+ * @return Number of characters written, or HV_EFAULT if the buffer is invalid.
+ */
+int hv_console_write(HV_VirtAddr bytes, int len);
+
+
+/** Dispatch the next interrupt from the client downcall mechanism.
+ *
+ * The hypervisor uses downcalls to notify the client of asynchronous
+ * events. Some of these events are hypervisor-created (like incoming
+ * messages). Some are regular interrupts which initially occur in
+ * the hypervisor, and are normally handled directly by the client;
+ * when these occur in a client's interrupt critical section, they must
+ * be delivered through the downcall mechanism.
+ *
+ * A downcall is initially delivered to the client as an INTCTRL_1
+ * interrupt. Upon entry to the INTCTRL_1 vector, the client must
+ * immediately invoke the hv_downcall_dispatch service. This service
+ * will not return; instead it will cause one of the client's actual
+ * downcall-handling interrupt vectors to be entered. The EX_CONTEXT
+ * registers in the client will be set so that when the client irets,
+ * it will return to the