cell->comm_page.comm_region.pm_timer_address =
system_config->platform_info.x86.pm_timer_address;
+ cell->comm_page.comm_region.pm_timer_val_ext =
+ system_config->platform_info.x86.pm_timer_val_ext;
+
return 0;
error_iommu_exit:
COMM_REGION_GENERIC_HEADER;
__u16 pm_timer_address;
-};
+ __u8 pm_timer_val_ext;
+} __attribute__((packed));
static inline __u32 jailhouse_call(__u32 num)
{
struct {
__u64 mmconfig_base;
__u8 mmconfig_end_bus;
- __u8 padding[5];
+ __u8 padding[4];
+ __u8 pm_timer_val_ext;
__u16 pm_timer_address;
__u64 dmar_unit_base[JAILHOUSE_MAX_DMAR_UNITS];
} __attribute__((packed)) x86;
comm_region->cell_state = JAILHOUSE_CELL_RUNNING_LOCKED;
+ pm_timer_init();
init_apic();
while (!terminate) {
int bdf;
printk_uart_base = UART_BASE;
+ pm_timer_init();
bdf = pci_find_device(PCI_ID_ANY, PCI_ID_ANY, 0);
if (bdf < 0) {
printk_uart_base = UART_BASE;
printk("Hello from this tiny cell!\n");
+ pm_timer_init();
+
start = pm_timer_read();
for (n = 0; n < 10; n++) {
do {
void inmate_main(void);
+void pm_timer_init(void);
unsigned long pm_timer_read(void);
void delay_us(unsigned long microsecs);
unsigned long apic_timer_init(unsigned int vector);
* Jailhouse, a Linux-based partitioning hypervisor
*
* Copyright (c) Siemens AG, 2013, 2014
+ * Copyright (c) Valentine Sinitsyn, 2014
*
* Authors:
* Jan Kiszka <jan.kiszka@siemens.com>
+ * Valentine Sinitsyn <valentine.sinitsyn@gmail.com>
*
* This work is licensed under the terms of the GNU GPL, version 2. See
* the COPYING file in the top-level directory.
#include <inmate.h>
#define PM_TIMER_HZ 3579545
-#define PM_TIMER_OVERFLOW ((0x1000000 * 1000000000ULL) / PM_TIMER_HZ)
#define X2APIC_LVTT 0x832
#define X2APIC_TMICT 0x838
#define X2APIC_TDCR 0x83e
static unsigned long divided_apic_freq;
+static unsigned long pm_timer_overflow;
+
+void pm_timer_init(void)
+{
+ /* Initialize pm_timer overflow value, as per ACPI 5.0, Sect. 5.2.9. */
+ if (comm_region->pm_timer_val_ext)
+ pm_timer_overflow =
+ ((0x100000000 * 1000000000ULL) / PM_TIMER_HZ);
+ else
+ pm_timer_overflow =
+ ((0x1000000 * 1000000000ULL) / PM_TIMER_HZ);
+}
unsigned long pm_timer_read(void)
{
tmr = (inl(comm_region->pm_timer_address) * NS_PER_SEC) / PM_TIMER_HZ;
if (tmr < last)
- overflows += PM_TIMER_OVERFLOW;
+ overflows += pm_timer_overflow;
last = tmr;
return tmr + overflows;
}
# Jailhouse, a Linux-based partitioning hypervisor
#
# Copyright (c) Siemens AG, 2014
+# Copyright (c) Valentine Sinitsyn, 2014
#
# This work is licensed under the terms of the GNU GPL, version 2. See
# the COPYING file in the top-level directory.
inputs['files'].add('/sys/bus/pci/devices/*/class')
inputs['files'].add('/sys/devices/system/cpu/cpu*/uevent')
inputs['files'].add('/sys/firmware/acpi/tables/MCFG')
+inputs['files'].add('/sys/firmware/acpi/tables/FACP')
## optional files
inputs['files_opt'].add('/sys/class/dmi/id/product_name')
inputs['files_opt'].add('/sys/class/dmi/id/sys_vendor')
return pm_timer_base
+def parse_facp():
+ tmr_val_ext = 0
+ with input_open('/sys/firmware/acpi/tables/FACP', 'rb') as f:
+ signature = f.read(4)
+ if signature != b'FACP':
+ raise RuntimeError('FACP: incorrect input file format %s' %
+ signature)
+ f.seek(112)
+ (flags,) = struct.unpack('>I', f.read(4))
+ tmr_val_ext = (flags & 256) >> 8
+ return tmr_val_ext
+
+
class MMConfig:
def __init__(self, base, end_bus):
self.base = base
pm_timer_base = parse_ioports()
+pm_timer_val_ext = parse_facp()
f = open(options.file, 'w')
tmpl = Template(filename=os.path.join(options.template_dir,
cpucount=cpucount,
ioapic_id=ioapic_id,
pm_timer_base=pm_timer_base,
+ pm_timer_val_ext=pm_timer_val_ext,
mmconfig=mmconfig,
dmar_units=dmar_units))
.mmconfig_base = ${hex(mmconfig.base)},
.mmconfig_end_bus = ${hex(mmconfig.end_bus)},
.pm_timer_address = ${hex(pm_timer_base)},
+ .pm_timer_val_ext = ${pm_timer_val_ext},
% if dmar_units:
.dmar_unit_base = {
% for d in dmar_units: