arch/x86/platform/uv/uv_time.c

Source file repositories/reference/linux-study-clean/arch/x86/platform/uv/uv_time.c

File Facts

System
Linux kernel
Corpus path
arch/x86/platform/uv/uv_time.c
Extension
.c
Size
9255 bytes
Lines
394
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct uv_rtc_timer_head {
	spinlock_t	lock;
	/* next cpu waiting for timer, local node relative: */
	int		next_cpu;
	/* number of cpus on this node: */
	int		ncpus;
	struct {
		int	lcpu;		/* systemwide logical cpu number */
		u64	expires;	/* next timer expiration for this cpu */
	} cpu[] __counted_by(ncpus);
};

/*
 * Access to uv_rtc_timer_head via blade id.
 */
static struct uv_rtc_timer_head		**blade_info __read_mostly;

static int				uv_rtc_evt_enable;

/*
 * Hardware interface routines
 */

/* Send IPIs to another node */
static void uv_rtc_send_IPI(int cpu)
{
	unsigned long apicid, val;
	int pnode;

	apicid = cpu_physical_id(cpu);
	pnode = uv_apicid_to_pnode(apicid);
	val = (1UL << UVH_IPI_INT_SEND_SHFT) |
	      (apicid << UVH_IPI_INT_APIC_ID_SHFT) |
	      (X86_PLATFORM_IPI_VECTOR << UVH_IPI_INT_VECTOR_SHFT);

	uv_write_global_mmr64(pnode, UVH_IPI_INT, val);
}

/* Check for an RTC interrupt pending */
static int uv_intr_pending(int pnode)
{
	return uv_read_global_mmr64(pnode, UVH_EVENT_OCCURRED2) &
		UVH_EVENT_OCCURRED2_RTC_1_MASK;
}

/* Setup interrupt and return non-zero if early expiration occurred. */
static int uv_setup_intr(int cpu, u64 expires)
{
	u64 val;
	unsigned long apicid = cpu_physical_id(cpu);
	int pnode = uv_cpu_to_pnode(cpu);

	uv_write_global_mmr64(pnode, UVH_RTC1_INT_CONFIG,
		UVH_RTC1_INT_CONFIG_M_MASK);
	uv_write_global_mmr64(pnode, UVH_INT_CMPB, -1L);

	uv_write_global_mmr64(pnode, UVH_EVENT_OCCURRED2_ALIAS,
			      UVH_EVENT_OCCURRED2_RTC_1_MASK);

	val = (X86_PLATFORM_IPI_VECTOR << UVH_RTC1_INT_CONFIG_VECTOR_SHFT) |
		((u64)apicid << UVH_RTC1_INT_CONFIG_APIC_ID_SHFT);

	/* Set configuration */
	uv_write_global_mmr64(pnode, UVH_RTC1_INT_CONFIG, val);
	/* Initialize comparator value */
	uv_write_global_mmr64(pnode, UVH_INT_CMPB, expires);

	if (uv_read_rtc(NULL) <= expires)
		return 0;

	return !uv_intr_pending(pnode);
}

/*
 * Per-cpu timer tracking routines
 */

static __init void uv_rtc_deallocate_timers(void)
{
	int bid;

	for_each_possible_blade(bid) {
		kfree(blade_info[bid]);
	}
	kfree(blade_info);
}

/* Allocate per-node list of cpu timer expiration times. */
static __init int uv_rtc_allocate_timers(void)
{

Annotation

Implementation Notes